rust 为什么if-let需要用Some Package ?

wf82jlnq  于 2022-11-12  发布在  其他
关注(0)|答案(4)|浏览(240)

我是Rust的新手,刚刚遇到了一个很好的if-let结构。我有两个值ab,它们都是Option。我使用if-let如下:

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

这是可行的,但我不明白为什么我需要 Package 我的值,如Some(a),这已经是一个Option
Option不是已经是SomeNone中的一个吗?

wfypjpf4

wfypjpf41#

这是在rust中使用 * 模式匹配 * 的地方之一。

let x: Option<i32> = Some(42);

if let Some(x) = x {
    println!("{}", x);
}

Rust知道xOption类型,而这是一个枚举,有两种可能的变体。因此,这个模式匹配表示的是查看x,并将其与Some(x)进行比较。如果xNone,则匹配将失败(因为NoneSome(_)是不同的变量)。但是如果xSome,则模式将匹配**,并且Some中的值将被赋给变量x**。这将依次 * 遮蔽 * 前一个变量x,并且仅在此if let范围内有效
你所做的实际上是相同的,只是你匹配作为一个模式元组的两个选项。阅读这本书的chapter模式匹配更好地理解它,并看到所有其他地方,你可以找到它在生 rust 。

a9wyjsp7

a9wyjsp72#

这里需要注意的是,你没有 Package 你的值。当你使用if let Some(x) = y {时,你是在测试变量y是否匹配模式Some(x),如果匹配,就绑定x的值,使其成为选项 Package 的内容。你可以在here一书中阅读模式匹配
在你的例子中,你在两边都使用了ab,这有点误导人。你用新的变量遮蔽了原来的变量。你可以写if let (Some(x), Some(y)) = (a, b) {,它也可以工作,但是ab仍然是选项,xy可以作为先前 Package 的值。
另外,print语句需要传入ab。假定原始代码中确实有这两个参数。

woobm2wo

woobm2wo3#

您正在将“maybe-Some“的内容解包到它所保存的值,并且只有当两者都是Some时才进入该块。(而不是仅仅复制),并且在None时根本不运行?您的代码正在执行有意义的工作,测试Some ness,并使用原始Some对象的内容解包(和隐藏)原始ab。如果没有Some,Rust就无法自行推断测试和解包。

jjhzyzn0

jjhzyzn04#

首先,让我们暂时忘记元组,它只是这个问题的噪音。
您不需要 Package 它们,您可以执行以下操作:

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

但是if的意义何在呢?在Rust中,这样的赋值从来不会失败!
实际上,当你编写一个let LEFT = RIGHT;时,LEFT部分在技术上被称为 binding,这是一种将名称(变量)* 绑定 * 到值的特殊语法。
一般来说,绑定可能会出错,如果您键入let Some(inner_a) = a;,则如果aSome(42),则inner_a将绑定到42;但是如果a是无, the variable inner_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;DR;=左边的Some()不是在 * Package * 值,而是在 * 展开 * 它!

相关问题