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 块。

条件操作数必须是一个具有布尔类型表达式或一个条件 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` 可以用作表达式。
let y = if 12 * 15 > 150 {
    "Bigger"
} else {
    "Smaller"
};
assert_eq!(y, "Bigger");
}

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

#![allow(unused)]
fn main() {
fn diverging_condition() -> ! {
    // 因为条件表达式发散而发散
    if loop {} {
        ()
    } else {
        ()
    };
    // 上面的分号很重要:`if` 表达式的类型是 `()`,
    // 尽管它发散了。当最终体表达式被省略时,体的类型
    // 被推断为 !,因为函数体发散。如果没有分号,
    // `if` 将是类型为 `()` 的尾部表达式,这将无法匹配返回类型 `!`。
}

fn diverging_arms() -> ! {
    // 因为所有分支都发散而发散
    if true {
        loop {}
    } else {
        loop {}
    }
}
}

if let 模式

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

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

#![allow(unused)]
fn main() {
let dish = ("Ham", "Eggs");

// 因为模式被反驳,此体将被跳过。
if let ("Bacon", b) = dish {
    println!("Bacon is served with {}", b);
} else {
    // 改为执行此块。
    println!("No bacon will be served");
}

// 此体将执行。
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);
}
}

条件链

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

类似于 && LazyBooleanExpression,每个操作数从左到右求值,直到某个操作数求值为 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 受检者的歧义和优先级,所有条件操作数都不能是 || 惰性布尔运算符表达式。如果需要 || 表达式,可以使用括号。例如:

#![allow(unused)]
fn main() {
let foo = Some(123);
let condition1 = true;
let condition2 = false;
// 此处需要括号。
if let Some(x) = foo && (condition1 || condition2) { /*...*/ }
}

2024 Edition differences

在 2024 版本之前,不支持 let 链。即 LetChain 语法在 if 表达式中是不允许的。