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 if 或 else 块。

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

如果所有 if 和 else 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);
}
}

条件链

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

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

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

以下是链接多个表达式、混合 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 语法。