【问题标题】:Cannot change one value of an enum because it's a re-assignment of an immutable variable无法更改枚举的一个值,因为它是对不可变变量的重新分配
【发布时间】:2016-10-07 13:34:28
【问题描述】:

我有包含变量的枚举:

enum Asymmetric {
    One(i32),
    Two(i32, i32),
}

我只想更改现有枚举的一个字段,而不重新分配整个枚举。我的代码(playground):

// Does not compile
fn main() {
    let two = Asymmetric::Two(4, 5);
    let mut vec = vec![two];
    foo(&mut vec[0]);
}

fn foo(baa: &mut Asymmetric) {
    match baa {
        &mut Asymmetric::Two(x0, x1) => {
            x0 = 6;
        }
        _ => {}
    }
}

这会导致这个错误:

error[E0384]: re-assignment of immutable variable `x0`
  --> src/main.rs:16:13
   |
15 |         &mut Asymmetric::Two(x0, x1) => {
   |                              -- first assignment to `x0`
16 |             x0 = 6;
   |             ^^^^^^ re-assignment of immutable variable

【问题讨论】:

    标签: enums rust


    【解决方案1】:

    感谢“匹配人体工程学”(在 Rust 1.26 中引入,proposed here),您可以这样编写代码:

    fn foo(baa: &mut Asymmetric) {
        match baa {
            Asymmetric::Two(x0, _) => {
                *x0 = 6;
            }
            _ => {}
        }
    }
    

    由于 baa 是一个可变引用,但您匹配的模式 (Asymmetric::Two(x0, _)) 不是,所以名称 x0 会自动绑定为可变引用。

    您也可以使用ref mut 手动执行此操作。请参阅此工作代码 (playground):

    fn foo(baa: &mut Asymmetric) {
        match *baa {
            Asymmetric::Two(ref mut x0, _) => {
                *x0 = 6;
            }
            _ => {}
        }
    }
    

    一些与您的错误无关但提高代码质量的小改动:

    • 通常你取消引用(使用*matched-on 值,而不是向匹配中的每个模式添加 &&mut
    • 如果您不需要绑定到该名称,则应使用 _ 作为名称占位符

    在您的情况下,您可以使用if let 进一步简化代码。每当您只对一个match-case 感兴趣时,您应该改用if let

    fn foo(baa: &mut Asymmetric) {
        if let Asymmetric::Two(x0, _) = baa {
            *x0 = 6;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多