为什么 if-let 需要用一些包装?

  • 本文关键字:包装 if-let rust
  • 更新时间 :
  • 英文 :


我是 Rust 的新手,刚刚遇到了漂亮的if-let结构。我有ab值,它们都是Option的。我按如下方式使用if-let

if let (Some(a), Some(b)) = (a, b) {
println!("You passed in {:?}, {:?}");
}

这有效,但我对为什么我需要包装我的价值观感到困惑,例如已经是OptionSome(a).

Option不是已经是SomeNone之一了吗?

这是在 rust 中使用模式匹配时的地方之一。在更简单的例子中:

let x: Option<i32> = Some(42);
if let Some(x) = x {
println!("{}", x);
}

Rust 知道x是一个Option类型,而这个枚举有两个可能的变体。所以这个模式匹配表达是什么看x,再和Some(x)比较。如果xNone则匹配将失败(因为NoneSome(_)是不同的变体)。但是,如果xSome则模式将匹配,并且Some中的值将分配给变量x。这将反过来隐藏以前的变量x,并且仅在此if let范围内有效。

您正在做的事情实际上是相同的,只是您匹配为两个选项的元组的模式。阅读《The Book》中关于模式匹配的这一章,以更好地理解它,并查看所有其他地方,你可以在 rust 中找到它。

这里要注意的是,你没有包装你的价值观。当您使用if let Some(x) = y {时,您正在测试变量y是否与模式Some(x)匹配,如果是,则将x的值绑定为选项包装的东西。你可以在这里阅读书中的模式匹配

在您的示例中,您在两侧都使用了ab这一事实有点误导。您正在用新变量遮蔽原始变量。你可以写if let (Some(x), Some(y)) = (a, b) {它本来可以工作,但ab仍然是选项,xy将作为先前包装的值提供。

此外,您的打印语句需要传入ab。想必你的原始代码确实有它们。

您将"maybe-Some"的内容解压缩到它所包含的值,并且只有在两者都Some时才进入块。如果你可以写if let (a, b) = (a, b),它怎么知道解压缩(而不仅仅是复制)并且在None时根本不运行?您的代码正在执行有意义的工作,既要测试Some性,又要解压缩(和重影)原始a,并使用它们最初持有的Some对象的内容进行b。如果你没有Some,测试和拆包都不是 Rust 可以自己推断的东西。

首先,让我们暂时忘记元组,这只是这个问题的噪音。

您不需要包装它们,您可以执行以下操作:

if let a = a {
println!("{:?}", a);
}

但是if的意义何在?在 Rust 中,这样的任务永远不会失败!

实际上,当您编写let LEFT = RIGHT;时,LEFT部分在技术上称为绑定,这是一种将名称(变量)绑定到值的特殊语法。

一般来说,绑定可能是错误的,如果你键入let Some(inner_a) = a;那么如果aSome(42)那么inner_a将绑定到42;但是如果a是无的,, the variableinner_a'将被取消分配,这不好。

解决这个问题的常用方法是使用匹配,尝试多个绑定,直到一个成功:

let inner_a = match a {
Some(x) => x,
None => 0,
};

if let构造只是匹配的语法糖:

if let Some(inner_a) = a {
do_something(inner_a);
}

脱糖为:

match a {
Some(inner_a) => {
do_something(inner_a);
}
_ => {} //catch-all binding
}

TL;博士;=左侧的Some()不是包装值,而是解开它!

最新更新