If and if let expressions - The Rust Reference

# `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 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)]
    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` MatchArmPatterns `=` 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)]
    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 ) { .. }