Skip to content

Commit

Permalink
Document interaction of | patterns and pattern guards
Browse files Browse the repository at this point in the history
  • Loading branch information
Havvy committed Jul 30, 2018
1 parent 219e261 commit 249bc2f
Showing 1 changed file with 30 additions and 8 deletions.
38 changes: 30 additions & 8 deletions src/expressions/match-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
> _MatchArmGuard_ :\
>    `if` [_Expression_]
A `match` expression branches on a *pattern*. The exact form of matching that
occurs depends on the pattern. Patterns consist of some combination of
A *`match` expression* branches on a pattern. The exact form of matching that
occurs depends on the pattern. *Patterns* consist of some combination of
literals, destructured arrays or enum constructors, structs and tuples,
variable binding specifications, wildcards (`..`), and placeholders (`_`). A
`match` expression has a *head expression*, which is the value to compare to
Expand Down Expand Up @@ -99,11 +99,12 @@ symbols, as appropriate. For example, these two matches on `x: &i32` are
equivalent:

```rust
# let x = &3;
let y = match *x { 0 => "zero", _ => "some" };
let z = match x { &0 => "zero", _ => "some" };
let int_reference = &3;

assert_eq!(y, z);
let a = match *int_reference { 0 => "zero", _ => "some" };
let b = match int_reference { &0 => "zero", _ => "some" };

assert_eq!(a, b);
```

Subpatterns can also be bound to variables by the use of the syntax `variable @
Expand Down Expand Up @@ -132,7 +133,7 @@ let message = match x {
assert_eq!(message, "a few");
```

Other forms of [range] \(`..` for an exclusive range, or any range with one or
Other forms of [range] \(e.g `..` for an exclusive range, or any range with one or
both endpoints left unspecified) are not supported in matches. The
syntax `...` is also accepted for inclusive ranges in patterns only, for
backwards compatibility.
Expand All @@ -159,11 +160,16 @@ match v[..] {
}
```

Finally, match patterns can accept *pattern guards* to further refine the
Finally, match arms can accept *pattern guards* to further refine the
criteria for matching a case. Pattern guards appear after the pattern and
consist of a bool-typed expression following the `if` keyword. A pattern guard
may refer to the variables bound within the pattern they follow.

When the pattern matches successfully, the pattern guard expression is executed.
If the expression is truthy, the pattern is successfully matched against.
Otherwise, the next pattern, including other matches with the `|` operator in
the same arm, is tested.

```rust
# let maybe_digit = Some(0);
# fn process_digit(i: i32) { }
Expand All @@ -175,6 +181,21 @@ let message = match maybe_digit {
};
```

> Note: Multiple matches using the `|` operator can cause the pattern guard and
> and side effects it has to execute multiple times. For example:
>
> ```rust
> use std::cell::Cell;
> fn main() {
> let i : Cell<i32> = Cell::new(0);
> match 1 {
> 1 | _ if { i.set(i.get() + 1); false } => {}
> _ => {}
> }
> assert_eq!(i.get(), 2);
> }
> ```
## Attributes on match arms
Outer attributes are allowed on match arms. The only attributes that have
Expand All @@ -190,3 +211,4 @@ meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].
[_OuterAttribute_]: attributes.html
[`cfg`]: attributes.html#conditional-compilation
[lint check attributes]: attributes.html#lint-check-attributes
[range]: expressions/range-expr.html

0 comments on commit 249bc2f

Please sign in to comment.