为什么 "break" 在结束 "loop" 时不需要分号?

Why does "break" not need a semicolon when ending a "loop"?

摘自 Chapter 3.5 的 Rust 书:

we use the break keyword with the value counter * 2. After the loop, we use a semicolon to end the statement that assigns the value to result.

加上代码片段:

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!("The result is {}", result);
}

我明白这是如何工作的以及为什么结果是 20,但我注意到如果我删除包含 break 关键字的行上的分号,程序是等效的。

为什么在这种情况下分号是可选的?

一个较短的例子:

let _: i32 = loop {
    if true {
        break 3; // ()
    }
};

这只是分号不影响预期结果的另一个例子。首先,分号的插入引入了一个表达式语句,其计算结果为单位类型 ()。由于 loopif 表达式继续接受评估为相同类型 () 的代码块,因此所有类型都是一致的。

let _: i32 = loop {
    if true {
        break 3 // !
    }
};

如果去掉分号,break 将被计算为 the never type !,这会强制转换为任何其他类型。这意味着它将满足外部作用域期望的任何类型。所以一切都一样,只要您不尝试在 if 块结束之前附加任何其他语句。

breakreturn 的计算结果都是 !,因为它们的副作用意味着该程序不会按照自然的工作流程进行。

另请参阅:

The Rust Language Reference on Expression Statements:

An expression statement is one that evaluates an expression and ignores its result. As a rule, an expression statement's purpose is to trigger the effects of evaluating its expression.

An expression that consists of only a block expression or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon.

我想这纯粹是为了美学和人体工程学,因为几乎所有东西都是 Rust 的表达。如果在所有表达式之后尾随分号是强制性的,那么我们将不得不使用看起来很糟糕的分号来终止 if-else 块(也是表达式):

if {
    // do something
} else {
    // do something else
}; // <- gross

同样,我们可以省略所有控制流表达式的尾随分号,因为它们会产生控制流,因此分号的典型功能,即丢弃表达式的结果并评估为 (),变成无关紧要。

fn five() -> i32 {
    return 5 // to semicolon or not to semicolon? it doesn't matter
}

在上面的例子中,我们是否用分号终止 return 5 都没有区别,因为无论如何都无法“捕获”该表达式的结果,因为它会产生控制流。对于 breakcontinue.

等其他控制流表达式也是如此