为什么_在声明结尾处销毁?

时间:2018-07-09 00:39:01

标签: syntax rust pattern-matching

我还看到了其他一些问题,answers指出let _ = foo()在语句末尾而不是作用域退出处销毁了结果,而let _a = foo()就是这样做的。 / p>

我找不到对此的任何正式描述,也找不到该语法的任何原理。

我对一些相互关联的东西感兴趣:

  • 官方文档中甚至没有提及它?
  • 此选择背后的历史是什么?它仅仅是Rust的绑定/解构规则的自然产物吗?它是从另一种语言继承的吗?还是它有其他起源?
  • 这种语法是否有一些用例无法通过显式作用域实现?

2 个答案:

答案 0 :(得分:7)

  

这仅仅是Rust的绑定/解构规则的自然产物吗?

是的。您使用_来表示您不关心模式中的值,并且一开始就不应该绑定该值。如果值从未绑定到变量,则没有任何要保留的值,因此必须将其删除。

All the Places Patterns Can Be Used

  • match武器
  • 有条件的if let表达式
  • while let条件循环
  • for循环
  • let声明
  • 功能参数
  

在官方文档中甚至没有提及它?

Ignoring an Entire Value with _

请注意,_不是a valid identifier,因此您不能将其用作名称:

fn main() {
    let _ = 42;
    println!("{}", _);
}
error: expected expression, found reserved identifier `_`
 --> src/main.rs:3:20
  |
3 |     println!("{}", _);
  |                    ^ expected expression
  

使用显式作用域实现

我想您可以走这条路线,然后做一些表达式来“徘徊”直到范围结束,但是我看不出任何价值:

let _ = vec![5];    
vec![5]; // Equivalent
// Gotta wait for the scope to end to clean these up, or call `drop` explicitly

答案 1 :(得分:5)

使用let _ = foo()的唯一原因是当函数要求您使用其结果,并且知道您不需要它时。否则,这:

let _ = foo();

与此完全相同:

foo();

例如,假设foo具有这样的签名:

fn foo() -> Result<String, ()>;

如果不使用结果,将会收到警告,因为Result具有#[must_use] attribute。立即进行销毁和忽略结果是一种避免在可能的情况下避免出现此警告的简洁方法,而无需引入可以在整个范围内使用的新变量。

如果您不对结果进行模式匹配,则foo函数返回后,该值将被删除。不管您明确表示不想要还是不使用它,Rust的行为都一样是合理的。