if and if let expressions
if expressions
Syntax
IfExpression :
ifExpressionexcept struct expression BlockExpression
(else( BlockExpression | IfExpression | IfLetExpression ) )?
An if expression is a conditional branch in program control. The form of an
if expression is a condition expression, followed by a consequent block, any
number of else if conditions and blocks, and an optional trailing else
block. The condition expressions must have type bool. If a condition
expression evaluates to true, the consequent block is executed and any
subsequent else if or else block is skipped. If a condition expression
evaluates to false, the consequent block is skipped and any subsequent else if condition is evaluated. If all if and else if conditions evaluate to
false then any else block is executed. An if expression evaluates to the
same value as the executed block, or () if no block is evaluated. An if
expression must have the same type in all situations.
#![allow(unused_variables)] fn main() { let x = 3; if x == 4 { println!("x is four"); } else if x == 3 { println!("x is three"); } else { println!("x is something else"); } let y = if 12 * 15 > 150 { "Bigger" } else { "Smaller" }; assert_eq!(y, "Bigger"); }
if let expressions
Syntax
IfLetExpression :
ifletMatchArmPatterns=Expressionexcept struct or lazy boolean operator expression BlockExpression
(else( BlockExpression | IfExpression | IfLetExpression ) )?
An if let expression is semantically similar to an if expression but in
place of a condition expression it expects the keyword let followed by a
pattern, an = and a scrutinee expression. If the value of the scrutinee
matches the pattern, the corresponding block will execute. Otherwise, flow
proceeds to the following else block if it exists. Like if expressions,
if let expressions have a value determined by the block that is evaluated.
#![allow(unused_variables)] fn main() { let dish = ("Ham", "Eggs"); // this body will be skipped because the pattern is refuted if let ("Bacon", b) = dish { println!("Bacon is served with {}", b); } else { // This block is evaluated instead. println!("No bacon will be served"); } // this body will execute if let ("Ham", b) = dish { println!("Ham is served with {}", b); } if let _ = 5 { println!("Irrefutable patterns are always true"); } }
if and if let expressions can be intermixed:
#![allow(unused_variables)] fn main() { let x = Some(3); let a = if let Some(1) = x { 1 } else if x == Some(2) { 2 } else if let Some(y) = x { y } else { -1 }; assert_eq!(a, 3); }
An if let expression is equivalent to a match expression as follows:
if let PATS = EXPR {
/* body */
} else {
/*else */
}
is equivalent to
match EXPR {
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:
#![allow(unused_variables)] fn main() { 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. 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). When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below:
// Before...
if let PAT = EXPR && EXPR { .. }
// After...
if let PAT = ( EXPR && EXPR ) { .. }
// Before...
if let PAT = EXPR || EXPR { .. }
// After...
if let PAT = ( EXPR || EXPR ) { .. }