Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

if 表达式

if 表达式的语法是一个或多个用 && 分隔的条件操作数序列,后跟结果块、任意数量的 else if 条件和块,以及可选的尾部 else 块。

条件操作数必须是具有布尔类型Expression 或条件 let 匹配。

如果所有条件操作数都求值为 true 并且所有 let 模式都成功匹配其审查者,则执行结果块并跳过任何后续的 else ifelse 块。

如果任何条件操作数求值为 false 或任何 let 模式未匹配其审查者,则跳过结果块并求值任何后续的 else if 条件。

如果所有 ifelse if 条件都求值为 false,则执行任何 else 块。

if 表达式求值为与执行的块相同的值,如果没有块被求值则为 ()

if 表达式在所有情况下必须具有相同的类型。

#![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");
}

// `if` can be used as an expression.
let y = if 12 * 15 > 150 {
    "Bigger"
} else {
    "Smaller"
};
assert_eq!(y, "Bigger");
}

如果条件表达式发散或所有分支都发散,则 if 表达式发散

#![allow(unused)]
fn main() {
fn diverging_condition() -> ! {
    // Diverges because the condition expression diverges
    if loop {} {
        ()
    } else {
        ()
    };
    // The semicolon above is important: The type of the `if` expression is
    // `()`, despite being diverging. When the final body expression is
    // elided, the type of the body is inferred to ! because the function body
    // diverges. Without the semicolon, the `if` would be the tail expression
    // with type `()`, which would fail to match the return type `!`.
}

fn diverging_arms() -> ! {
    // Diverges because all arms diverge
    if true {
        loop {}
    } else {
        loop {}
    }
}
}

if let 模式

if 条件中的 let 模式允许在模式成功匹配时将新变量绑定到作用域中。

以下示例说明了使用 let 模式的绑定:

#![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");
}
}

可以使用 | 运算符指定多个模式。这与 [match 表达式]中的 | 具有相同的语义:

#![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);
}
}

条件链

多个条件操作数可以用 && 分隔。

类似于 && 惰性布尔表达式,每个操作数从左到右求值,直到操作数求值为 falselet 匹配失败,在这种情况下不求值后续操作数。

每个模式的绑定被放入作用域,以供下一个条件操作数和结果块使用。

以下是链接多个表达式、混合 let 绑定和布尔表达式、以及表达式能够引用先前表达式的模式绑定的示例:

#![allow(unused)]
fn main() {
fn single() {
    let outer_opt = Some(Some(1i32));

    if let Some(inner_opt) = outer_opt
        && let Some(number) = inner_opt
        && number == 1
    {
        println!("Peek a boo");
    }
}
}

上面的代码等同于以下不使用条件链的代码:

#![allow(unused)]
fn main() {
fn nested() {
    let outer_opt = Some(Some(1i32));

    if let Some(inner_opt) = outer_opt {
        if let Some(number) = inner_opt {
            if number == 1 {
                println!("Peek a boo");
            }
        }
    }
}
}

如果任何条件操作数是 let 模式,则由于 let 审查者的歧义和优先级,任何条件操作数都不能是 || 惰性布尔运算符表达式

Example

如果需要 || 表达式,则可以使用括号。例如:

#![allow(unused)]
fn main() {
let foo = Some(123);
let condition1 = true;
let condition2 = false;
if let Some(x) = foo
    // Parentheses are required here.
    && (condition1 || condition2)
{}
}

2024 Edition differences

在 2024 版本之前,不支持 let 链。也就是说,if 表达式中不允许使用 LetChain 语法。