修改Option内部的struct字段

mbr*_*brt 2 rust

我在更改选项内部结构的字段时遇到问题.这是代码:

struct MyStruct {
    field1 : i32,
    field2 : i32,
    // and many more...
}

impl MyStruct {
    pub fn field1(&mut self, field1 : i32) -> &mut Self {
        self.field1 = field1;
        self
    }
}

fn foo() -> Option<MyStruct> {
    None
}

fn bar() -> Option<MyStruct> {
    foo().as_mut().map(|s| s.field1(5))
}

fn main() {
    bar();
}
Run Code Online (Sandbox Code Playgroud)

主要思想bar()Option<MyStruct>从另一个函数返回一个Option<MyStruct>,更改该结构的字段(如果结果不是None)并返回结果Option<MyStruct>.

结构实现了构建器模式,所以我使用它.

在这种情况下,我收到以下错误:

test.rs:18:5: 18:40 error: mismatched types:
expected `core::option::Option<MyStruct>`,
    found `core::option::Option<&mut MyStruct>`
(expected struct `MyStruct`,
    found &-ptr) [E0308]
test.rs:18     foo().as_mut().map(|s| s.field1(5))
Run Code Online (Sandbox Code Playgroud)

我也尝试使用Option.take()和更改构建器方法的签名pub fn field1(mut self, field1 : i32) -> Self,但它们都不起作用.

如何使此代码有效?

我知道我可以创建另一个Option并将输入的每个字段映射到输出的相应字段,但是MyStruct有很多字段,这很乏味.

Vee*_*rac 8

说实话,我会用显而易见的方式来做:

fn bar() -> Option<MyStruct> {
    let mut val = foo();
    if let Some(ref mut s) = val {
        s.field1(5);
    }
    val
}
Run Code Online (Sandbox Code Playgroud)

它比 using 更长map,但我发现 usingmap进行变异很不舒服,而且我选择的显式变异也会产生更好的组装。


Vla*_*eev 5

根本没有理由使用as_mut().因为您需要MyStruct按值返回,所以您可以map选择:

fn bar() -> Option<MyStruct> {
    foo().map(|mut s| { s.field1(5); s })
}
Run Code Online (Sandbox Code Playgroud)

而已.您需要s使用mut相同的原因进行标记let.