diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index 25d3e5aec..5501dc86f 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -44,7 +44,7 @@ assert_eq!(y, "Bigger"); > **Syntax**\ > _IfLetExpression_ :\ ->    `if` `let` [_Pattern_] `=` [_Expression_]_except struct or lazy boolean operator expression_ +>    `if` `let` [_MatchArmPatterns_] `=` [_Expression_]_except struct or lazy boolean operator expression_ > [_BlockExpression_]\ >    (`else` ( > [_BlockExpression_] @@ -95,10 +95,10 @@ let a = if let Some(1) = x { assert_eq!(a, 3); ``` -An `if let` expression is equivalent to a `match` expression as follows: +An `if let` expression is equivalent to a [`match` expression] as follows: ```rust,ignore -if let PAT = EXPR { +if let PATS = EXPR { /* body */ } else { /*else */ @@ -109,11 +109,26 @@ is equivalent to ```rust,ignore match EXPR { - PAT => { /* body */ }, + PATS => { /* body */ }, _ => { /* else */ }, // () if there is no else } ``` +Multiple patterns may be specified with the `|` operator. This has the same semantics +as with `|` in `match` expressions: + +```rust +enum E { + X(u8), + Y(u8), + Z(u8), +} +let v = E::Y(12); +if let E::X(n) | E::Y(n) = v { + assert_eq!(n, 12); +} +``` + The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]). @@ -134,9 +149,10 @@ if let PAT = EXPR || EXPR { .. } if let PAT = ( EXPR || EXPR ) { .. } ``` -[_Expression_]: expressions.html [_BlockExpression_]: expressions/block-expr.html -[_Pattern_]: patterns.html +[_Expression_]: expressions.html [_LazyBooleanOperatorExpression_]: expressions/operator-expr.html#lazy-boolean-operators +[_MatchArmPatterns_]: expressions/match-expr.html [_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018 +[`match` expression]: expressions/match-expr.html [scrutinee]: glossary.html#scrutinee diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 07eacc502..7a2ae1863 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -67,7 +67,7 @@ while i < 10 { > **Syntax**\ > [_PredicatePatternLoopExpression_] :\ ->    `while` `let` [_Pattern_] `=` [_Expression_]except struct expression +>    `while` `let` [_MatchArmPatterns_] `=` [_Expression_]except struct expression > [_BlockExpression_] A `while let` loop is semantically similar to a `while` loop but in place of a @@ -90,11 +90,11 @@ while let _ = 5 { } ``` -A `while let` loop is equivalent to a `loop` expression containing a `match` -expression as follows. +A `while let` loop is equivalent to a `loop` expression containing a [`match` +expression] as follows. ```rust,ignore -'label: while let PAT = EXPR { +'label: while let PATS = EXPR { /* loop body */ } ``` @@ -104,12 +104,23 @@ is equivalent to ```rust,ignore 'label: loop { match EXPR { - PAT => { /* loop body */ }, + PATS => { /* loop body */ }, _ => break, } } ``` +Multiple patterns may be specified with the `|` operator. This has the same semantics +as with `|` in `match` expressions: + +```rust +let mut vals = vec![2, 3, 1, 2, 2]; +while let Some(v @ 1) | Some(v @ 2) = vals.pop() { + // Prints 2, 2, then 1 + println!("{}", v); +} +``` + ## Iterator loops > **Syntax**\ @@ -272,12 +283,11 @@ and the `loop` must have a type compatible with each `break` expression. expression `()`. [IDENTIFIER]: identifiers.html -[temporary values]: expressions.html#temporary-lifetimes - -[_Expression_]: expressions.html +[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels [_BlockExpression_]: expressions/block-expr.html +[_Expression_]: expressions.html +[_MatchArmPatterns_]: expressions/match-expr.html [_Pattern_]: patterns.html - -[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels - +[`match` expression]: expressions/match-expr.html [scrutinee]: glossary.html#scrutinee +[temporary values]: expressions.html#temporary-lifetimes diff --git a/src/expressions/match-expr.md b/src/expressions/match-expr.md index 3dd85e2f1..d032a3fcc 100644 --- a/src/expressions/match-expr.md +++ b/src/expressions/match-expr.md @@ -62,7 +62,8 @@ match x { Variables bound within the pattern are scoped to the match guard and the arm's expression. The [binding mode] (move, copy, or reference) depends on the pattern. -Multiple match patterns may be joined with the `|` operator: +Multiple match patterns may be joined with the `|` operator. Each pattern will be +tested in left-to-right sequence until a successful match is found. ```rust # let x = 9; @@ -73,11 +74,22 @@ let message = match x { }; assert_eq!(message, "a few"); + +// Demonstration of pattern match order. +struct S(i32, i32); + +match S(1, 2) { + S(z @ 1, _) | S(_, z @ 2) => assert_eq!(z, 1), + _ => panic!(), +} ``` -Please notice that the `2..=9` is a [Range Pattern], not a [Range Expression] -and, thus, only those types of ranges supported by range patterns can be used -in match arms. +> Note: The `2..=9` is a [Range Pattern], not a [Range Expression]. Thus, only +> those types of ranges supported by range patterns can be used in match arms. + +Every binding in each `|` separated pattern must appear in all of the patterns +in the arm. Every binding of the same name must have the same type, and have +the same binding mode. Match arms can accept _match guards_ to further refine the criteria for matching a case. Pattern guards appear after the pattern and @@ -85,7 +97,7 @@ 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. +If the expression evaluates to true, the pattern is successfully matched against. Otherwise, the next pattern, including other matches with the `|` operator in the same arm, is tested. @@ -104,15 +116,13 @@ let message = match maybe_digit { > and side effects it has to execute multiple times. For example: > > ```rust -> use std::cell::Cell; -> fn main() { -> let i : Cell = Cell::new(0); -> match 1 { -> 1 | _ if { i.set(i.get() + 1); false } => {} -> _ => {} -> } -> assert_eq!(i.get(), 2); +> # use std::cell::Cell; +> let i : Cell = Cell::new(0); +> match 1 { +> 1 | _ if { i.set(i.get() + 1); false } => {} +> _ => {} > } +> assert_eq!(i.get(), 2); > ``` ## Attributes on match arms