【问题标题】:Why is the semicolon after the return statement optional?为什么return语句后面的分号是可选的?
【发布时间】:2020-06-29 12:09:03
【问题描述】:

我想遍历Options 的列表。如果其中一个有值,我想返回一个错误。这是一个人为的例子:

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 中应该使用哪种形式:分号还是不使用分号?两者都被编译器接受并且似乎产生了相同的结果。

【问题讨论】:

标签: rust


【解决方案1】:

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

问题的症结在于return 在 Rust 中不是一个语句(本身),它是一个返回!1表达式

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

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

    Ok(())
}

请注意,我删除了 return 表达式周围的 {}=&gt; 的右边是一个表达式,return Err(value) 是一个表达式,它正好适合,不需要额外的绒毛。

1! 表示编程语言理论中的底层类型,没有实例的类型,用于表示发散的表达式。它也被称为 NEVER 类型。


正如Are semicolons optional in Rust? 中所述,表达式可以通过添加; 转换为Rust 中的语句。

由于=&gt; 的右侧需要一个表达式,因此您不能直接使用return Err(value);(因为它现在是一个语句),但您可以使用恰好包含语句的块表达式 ,并且可能是最终表达式。

因此,可选的;的一个属性:

  • 包含单个语句的块,没有最终表达式:{ return Err(value); }。它的类型是()
  • 仅包含最终表达式的块:{ return Err(value) }。它的类型是!

【讨论】:

  • 如果我想在 return 之前做一些事情,所以我不能使用 Some(value) => return value,怎么办?在这种情况下,惯用的形式是什么?我更新了我的问题。
  • @RichApodaca:在这种情况下,你需要一个块,然后运行cargo fmt。惯用语法被接受为默认的cargo fmt。但在实践中,两者都起作用并产生相同的结果,那么这真的很重要吗?
【解决方案2】:

; 可以在此处省略,因为 return 是一个计算结果为 ! type 的表达式,然后将其强制转换为空元组 (),因此所有匹配臂都具有相同的类型。

在惯用的 Rust 中应该使用哪种形式?

添加; 或删除周围的花括号是惯用的。这也是cargo fmt 所做的。

【讨论】:

  • 另外,块语句(例如for ... { ... } 循环)后面隐含一个分号,所以在某种意义上一个分号——一个不可见的。
  • 是的,在for 循环之后,但不是在return 语句之后。
猜你喜欢
  • 1970-01-01
  • 2018-06-09
  • 1970-01-01
  • 2021-11-14
  • 2018-01-23
  • 2011-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多