1 # `if` and `if let` expressions
5 > **<sup>Syntax</sup>**\
7 > `if` [_Expression_]<sub>_except struct expression_</sub> [_BlockExpression_]\
8 > (`else` (
11 > | _IfLetExpression_ ) )<sup>\?</sup>
13 An `if` expression is a conditional branch in program control. The form of an
14 `if` expression is a condition expression, followed by a consequent block, any
15 number of `else if` conditions and blocks, and an optional trailing `else`
16 block. The condition expressions must have type `bool`. If a condition
17 expression evaluates to `true`, the consequent block is executed and any
18 subsequent `else if` or `else` block is skipped. If a condition expression
19 evaluates to `false`, the consequent block is skipped and any subsequent `else
20 if` condition is evaluated. If all `if` and `else if` conditions evaluate to
21 `false` then any `else` block is executed. An if expression evaluates to the
22 same value as the executed block, or `()` if no block is evaluated. An `if`
23 expression must have the same type in all situations.
28 println!("x is four");
30 println!("x is three");
32 println!("x is something else");
35 let y = if 12 * 15 > 150 {
40 assert_eq!(y, "Bigger");
43 ## `if let` expressions
45 > **<sup>Syntax</sup>**\
46 > _IfLetExpression_ :\
47 > `if` `let` [_MatchArmPatterns_] `=` [_Expression_]<sub>_except struct or lazy boolean operator expression_</sub>
48 > [_BlockExpression_]\
49 > (`else` (
52 > | _IfLetExpression_ ) )<sup>\?</sup>
54 An `if let` expression is semantically similar to an `if` expression but in
55 place of a condition expression it expects the keyword `let` followed by a
56 pattern, an `=` and a [scrutinee] expression. If the value of the scrutinee
57 matches the pattern, the corresponding block will execute. Otherwise, flow
58 proceeds to the following `else` block if it exists. Like `if` expressions,
59 `if let` expressions have a value determined by the block that is evaluated.
62 let dish = ("Ham", "Eggs");
64 // this body will be skipped because the pattern is refuted
65 if let ("Bacon", b) = dish {
66 println!("Bacon is served with {}", b);
68 // This block is evaluated instead.
69 println!("No bacon will be served");
72 // this body will execute
73 if let ("Ham", b) = dish {
74 println!("Ham is served with {}", b);
78 println!("Irrefutable patterns are always true");
82 `if` and `if let` expressions can be intermixed:
86 let a = if let Some(1) = x {
88 } else if x == Some(2) {
90 } else if let Some(y) = x {
98 An `if let` expression is equivalent to a [`match` expression] as follows:
112 PATS => { /* body */ },
113 _ => { /* else */ }, // () if there is no else
117 Multiple patterns may be specified with the `|` operator. This has the same semantics
118 as with `|` in `match` expressions:
127 if let E::X(n) | E::Y(n) = v {
132 The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_].
133 Use of a lazy boolean operator is ambiguous with a planned feature change
134 of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]).
135 When lazy boolean operator expression is desired, this can be achieved
136 by using parenthesis as below:
140 if let PAT = EXPR && EXPR { .. }
143 if let PAT = ( EXPR && EXPR ) { .. }
146 if let PAT = EXPR || EXPR { .. }
149 if let PAT = ( EXPR || EXPR ) { .. }
152 [_BlockExpression_]: block-expr.md
153 [_Expression_]: ../expressions.md
154 [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators
155 [_MatchArmPatterns_]: match-expr.md
156 [_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018
157 [`match` expression]: match-expr.md
158 [scrutinee]: ../glossary.md#scrutinee