为什么在return语句后面的分号是可选的?

6
我想遍历一个Option列表。如果其中有一个值,我想返回一个错误。这里有一个人为制造的例子:
fn test(options: &[Option<u8>]) -> Result<(), &u8> {
    for option in options {
        match option {
            None => (),
            Some(value) => {
                // do some stuff here, so I can't just go
                // Some(value) => return Err(value),
                return Err(value); // this semicolon is optional
            }
        }
    }

    Ok(())
}

再添加一个分号会导致错误,但删除该分号不会。

为什么return语句后面的分号是可选的?

在惯用的Rust中应该使用哪种形式:带分号还是不带分号?编译器都接受并似乎产生相同的结果。


2
FWIW — 如果 let Some(value) = options.iter().flatten().next() { return Err(value); } - Shepmaster
1
看起来你的问题可能已经被以下这些问题的答案解决了:Rust中使用return语句和省略分号有什么区别?; 在Rust中分号是可选的吗?; 为什么在函数中最后一条语句使用return被认为是不好的风格?; 在panic后放置分号有任何理由吗?。如果以上问题无法解决您的问题,请**[编辑]**您的问题以解释其中的区别。 - Shepmaster
2
这个回答解决了你的问题吗?在 Rust 中,使用 return 语句和省略分号有什么区别? - E net4
2个回答

10

为什么return语句后的分号是可选的?

问题的关键在于,在Rust中return不是一个独立的语句,而是一个返回!1表达式

这意味着您测试用例的惯用格式实际上是:

fn test(options: &[Option<u8>]) -> Result<(), &u8> {
    for option in options {
        match option {
            None => (),
            Some(value) => return Err(value),
        }
    }

    Ok(())
}
请注意,我删除了{}符号以及return表达式周围的括号。 =>右侧接受一个表达式,return Err(value)是一个表达式,可以直接使用,不需要额外的修饰。 1!表示编程语言理论中的底部类型,它是没有实例的类型,并用于表示发散的表达式。它也被称为NEVER类型。 正如在Are semicolons optional in Rust?中所解释的那样,在Rust中,通过添加;,可以将表达式转化为语句。
由于=>右侧需要一个表达式,因此不能直接使用return Err(value);(因为它现在是一个语句),但是您可以使用包含语句和可能的最终表达式的块表达式
因此,可选的;的一个属性:
  • 仅包含单个语句而没有最终表达式的块:{ return Err(value); },其类型为()
  • 仅包含最终表达式的块:{ return Err(value) },其类型为

如果我想在返回之前做一些事情,所以不能使用 Some(value) => return value,那么该怎么办呢?在这种情况下,惯用的形式是什么?我更新了我的问题。 - Rich Apodaca
@RichApodaca: 在这种情况下,您需要一个代码块,然后只需运行 cargo fmt。惯用语法被认为是 cargo fmt 的默认设置。 但实际上,两者都可以工作并产生相同的结果,所以这真的很重要吗? - Matthieu M.

5
; 可以省略,因为 return 是一个表达式,它的类型是 ! 类型,然后被强制转换为空元组 (),所以所有的匹配分支都有相同的类型。
哪种形式在 Rust 的惯用语中应该使用?
习惯用法是添加;或者去掉周围的花括号。这也是cargo fmt执行的操作。

此外,块语句(例如 for ... { ... } 循环)在其后隐含有一个分号,因此从某种意义上说,确实存在一个分号 -- 一个看不见的分号。 - Lambda Fairy
是的,在 for 循环之后,但不在 return 语句之后。 - Aloso

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