【问题标题】:Can the `let Some(var) = option;` syntax be used in a situation where it's known that it's not `None`?`let Some(var) = option;` 语法可以在已知不是 `None` 的情况下使用吗?
【发布时间】:2017-01-10 16:37:08
【问题描述】:

当已知选项变量不是None时,通常可以这样写:

let var = option_var.unwrap();

在我遇到的一种情况下,这导致了关于移出借用上下文的错误。

if let Some(var) = option_var { ... }

(很方便,因为它也允许Some(ref mut var) = option_var)。

这可行,但在这种情况下,我不希望这是一个 if 声明。 写入 let Some(var) = option_var; 失败,错误为“pattern None notcovered”。

要明确这个问题与借用的上下文无关

let Some(var) = option; 语法是否可以在已知不是None 的情况下使用?解决“模式None 未覆盖”警告?或者这在 if 语句之外根本不支持?

【问题讨论】:

  • “在一个案例中我遇到了”那个案例是什么?
  • stackoverflow.com/q/30463490/155423的副本; stackoverflow.com/q/30365055/155423;或任何105 other questions about "cannot move out of borrowed content"。太糟糕了,这里没有足够的细节来选择更好的副本。
  • 这个问题不是关于借用的上下文,而是关于使用let Some(var) = option_var - 如果它可能在 if 语句之外。
  • stackoverflow.com/questions/34953711/… 可能重复?答案是:不,你不能使用语法......幸运的是,在Option 的情况下,unwrap() 触手可及。为什么不使用它?
  • @LukasKalbertodt stackoverflow.com/questions/34953711 是一个相当模糊的问题,这个问题的答案不是这个问题的直接答案,所以不要认为它是重复的。这个问题很直接 - "can a 'let Some(var) = option_var;'在 if 语句之外使用表达式 - 是或否”,如果答案是否定的,那么这就是我想知道的全部。我问这个是因为警告没有明确说明它不受支持,这让我想如果我知道正确的编写方法 - 它可以工作。

标签: rust variable-assignment optional


【解决方案1】:

鉴于以下情况:

fn main() {
    let foo = Some(1);
    let Some(bar) = foo;
}

错误[E0005]:本地绑定中的可反驳模式:None 未涵盖

let Some(x) = y 引入了一个模式; letmatch 语句和函数参数是模式匹配上下文,但由于在这种情况下模式不涵盖其他可能的情况,因此它不是有效的模式匹配上下文。

let Some(x) = y 语句适用的唯一上下文是if let 表达式和while let 循环。

如果您确定(例如,使用较早的 assert!() 或“手动”引入)None 是不可能的,您可以使用 unwrap()

【讨论】:

  • Re: “但是由于在这种情况下模式不涵盖其他可能的情况,它不是有效的模式匹配上下文。” - 是否有可能满足这个约束?还是在任何情况下都要求if let ... etc一起使用?
  • let Some(x) = y 语句适用的唯一上下文是if let 表达式和while let 循环。 Option 是这样,但在一般的。一般来说,传递给let 的模式必须是无可辩驳的。对于 Option,由于它有两个变体,Some(_) 模式是可反驳的,这需要通过if let 进行测试。如果我们考虑一个只有一个变体的枚举,那么常规的 let Variant(_) = some_enum; 就可以正常工作。
【解决方案2】:

我刚刚遇到了类似的枚举问题,例如:

let SomeEnum::First(first) = item;

我知道itemSomeEnum::First。但是 Rust 不会让我编译。

绕过这个问题的一种方法是使用这样的宏:

    macro_rules! unwrap {
        ($enum:path, $expr:expr) => {{
            if let $enum(item) = $expr {
                item
            } else {
                panic!()
            }
        }};
    }

你可以像这样调用unwrap!

let first = unwrap!(SomeEnum::First, item);

PS。我在我的测试中使用它。它有助于缩短测试时间。

【讨论】:

    猜你喜欢
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多