【问题标题】:Is there a way to split up a variable inside an Option without having to use if statements?有没有办法在 Option 中拆分变量而不必使用 if 语句?
【发布时间】:2018-11-21 22:57:50
【问题描述】:

我希望下面的代码能够工作,但由于map() 拥有Option 的所有权,而且Option 似乎没有clone() 函数,因此以下代码无法编译。

fn main() {
    struct ItemA {
        a: String,
        b: String,
    }
    let foo = Some(ItemA {
        a: "A String".to_owned(),
        b: "B String".to_owned(),
    });
    // OR
    // let foo = None;

    let opA: Option<String> = foo.map(|c| c.a);
    let opB: Option<String> = foo.map(|c| c.b);
}
error[E0382]: use of moved value: `foo`
  --> src/main.rs:15:31
   |
14 |     let opA: Option<String> = foo.map(|c| c.a);
   |                               --- value moved here
15 |     let opB: Option<String> = foo.map(|c| c.b);
   |                               ^^^ value used here after move
   |
   = note: move occurs because `foo` has type `std::option::Option<main::ItemA>`, which does not implement the `Copy` trait

如果opA 可以拥有ItemA.a 的所有权(这样它就不必克隆字符串)并且opB 可以拥有ItemA.b 的所有权,那就太好了

这是否可以在不必使用 if 语句检查 OptionSomeNone、打开包装并将其单独包装备份的情况下进行。

【问题讨论】:

  • Idiomatic Rust 使用snake_case 表示变量、方法、宏和字段; UpperCamelCase 用于类型; SCREAMING_SNAKE_CASE 用于静态和常量。请改用op_a / op_b

标签: rust ownership


【解决方案1】:

您可以使用map_or_else

let (opA, opB) = foo.map_or_else(
    || (None, None),
    |c| (Some(c.a), Some(c.b))
);

如果fooNone,则调用第一个函数,并返回两个Nones。如果fooSome,则调用第二个函数并将成员拆分为一个元组。

当然,与简单的match 相比,这并不能真正为您节省多少,而且可能更难理解。

let (opA, opB) = match foo {
    None => (None, None),
    Some(c) => (Some(c.a), Some(c.b))
};

顺便说一句,Option 确实实现了Clone,但它要求包含的类型实现Clone

【讨论】:

    【解决方案2】:

    [T]这里似乎没有 clone()Option 函数 [...]

    如果内部类型也实现了clone,那就错了,there is。因此,在您的情况下,只需将 #[derive(Clone)] 添加到您的 struct ItemA

    接下来,您可以使用as_ref 创建一个Option&lt;&amp;T&gt;,然后使用map

    let op_a = foo.as_ref().map(|c| &c.a);
    let op_b = foo.as_ref().map(|c| &c.b);
    
    println!("{:?}", op_a);
    println!("{:?}", op_b);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-27
      • 1970-01-01
      • 2016-01-04
      相关资源
      最近更新 更多