Rust中分号是可选的吗?

78

由于在 Rust 中分号显然是可选的,那么,如果我这样做:

fn fn1() -> i32 {    
    let a = 1
    let b = 2
    3
}

我遇到了这个错误:

error: expected one of `.`, `;`, `?`, or an operator, found `let`
 --> src/main.rs:3:9
  |
2 |         let a = 1
  |                  - expected one of `.`, `;`, `?`, or an operator here
3 |         let b = 2
  |         ^^^ unexpected token
2个回答

158

它们是必需品。分号可以修改表达式语句的行为,所以是否使用它们应该是有意识的决定。

Rust 中几乎所有的东西都是表达式,表达式是返回值的东西。如果加上分号,就会抑制这个表达式的结果,这在大多数情况下是你想要的。

另一方面,这意味着,如果你在函数末尾使用一个没有分号的表达式,那么这个最后一个表达式的结果将被返回。同样的方法也适用于一个 match 语句中的块。

您可以在任何需要值的地方使用没有分号的表达式。

例如:

let a = {
    let inner = 2;
    inner * inner
};

这里的表达式 inner * inner 没有以分号结尾,所以它的值不会被压制。由于它是块中的最后一个表达式,它的值将被返回并赋给a。如果在同一行上放置一个分号,inner * inner 的值将不会返回。

对于你的特定情况,不抑制你的let语句的值是没有意义的,编译器正确地因此而报错。事实上,let 不是一个表达式。


2
你也可以查看关于表达式的 https://rustbyexample.com/expression.html,其中也提到了分号。 - nbro
@nbro的评论已经更新链接: https://doc.rust-lang.org/stable/rust-by-example/expression.html - Jasha
@nbro,文档链接已经失效。这个链接可以使用 => https://doc.rust-lang.org/rust-by-example/expression.html - atilkan

9
分号通常是不可选的,但在一些情况下是可以省略的。具体来说,在控制语句(例如forif/elsematch等)之后需要加上分号。
fn main() {
    let a: u32 = 5;
    if 5 == a {
        println!("Hello!");
    }
    if 5 == a {
        println!("Hello!");
    };
    for x in "World".chars() {
        println!("{}", x);
    }
    for x in "World".chars() {
        println!("{}", x);
    };
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1bf94760dccae285a2bdc9c44e8f658a

在某些情况下,这些语句需要有分号或不需要。如果你是从内部返回值,你不能有分号,如果你想要将变量设置为内部的值,则需要使用分号。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接