为什么在结束“循环”时“中断”不需要分号?

Pau*_*erg 2 syntax loops break keyword rust

摘自Rust 书的第 3.5 章

我们使用break带有 value的关键字counter * 2。在循环之后,我们使用分号结束为 赋值的语句result

加上代码片段:

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

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

    println!("The result is {}", result);
}
Run Code Online (Sandbox Code Playgroud)

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

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

E_n*_*ate 6

一个较短的例子:

let _: i32 = loop {
    if true {
        break 3; // ()
    }
};
Run Code Online (Sandbox Code Playgroud)

这只是分号不会干扰预期结果的另一个例子。一方面,分号的插入引入了一个表达式语句,其计算结果为单元类型()。由于loops 和if表达式继续接受计算为相同类型的代码块(),因此所有类型都符合要求。

let _: i32 = loop {
    if true {
        break 3 // !
    }
};
Run Code Online (Sandbox Code Playgroud)

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

无论breakreturn评估,以!作为其副作用意味着该程序将无法与自然的工作流程办理。

也可以看看:


kfe*_*v91 5

关于表达式语句的 Rust 语言参考:

表达式语句是一种计算表达式并忽略其结果的语句。通常,表达式语句的目的是触发计算其表达式的效果。

仅由块表达式或控制流表达式组成的表达式,如果在允许语句的上下文中使用,则可以省略尾随分号

我想这纯粹是为了美观和人体工程学,因为几乎所有东西都是 Rust 的表达。如果所有表达式后面都必须有尾随分号,那么我们就必须用分号来终止 if-else 块(它们也是表达式),这看起来很糟糕:

if {
    // do something
} else {
    // do something else
}; // <- gross
Run Code Online (Sandbox Code Playgroud)

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

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

return 5在上面的示例中,如果我们以分号终止或不以分号终止并没有什么区别,因为无论如何都无法“捕获”该表达式的结果,因为它会产生控制流。break对于其他控制流表达式(如和 )也是如此continue

  • @PaulRazvanBerg 实际上相反。如果没有关键字“return”,则会隐式返回 5,而分号会抑制该返回,而是返回“()”,这与函数签名不兼容。 (3认同)