if
and if let
expressions
if
expressions
Syntax
IfExpression :
if
Expressionexcept struct expression BlockExpression
(else
( BlockExpression | IfExpression | IfLetExpression ) )?
An if
expression is a conditional branch in program control.
The syntax of an if
expression is a condition operand, followed by a consequent block, any number of else if
conditions and blocks, and an optional trailing else
block.
The condition operands must have the boolean type.
If a condition operand evaluates to true
, the consequent block is executed and any subsequent else if
or else
block is skipped.
If a condition operand 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)] 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 :
if
let
Pattern=
Scrutineeexcept 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 operand it expects the keyword let
followed by a pattern, an =
and a scrutinee operand.
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)] 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)] 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)] 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 ) { .. }