我的枚举包含变量:
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
答案 0 :(得分:13)
感谢"匹配人体工程学" (在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;
}
_ => {}
}
}
与您的错误无关但会提高代码质量的一些细微更改:
*
编辑match
ed-on值,而不是将&
或&mut
添加到匹配中的每个模式_
作为名称占位符在您的情况下,您可以使用if let
进一步简化代码。如果您只对match
个案例感兴趣,则应使用if let
代替:
fn foo(baa: &mut Asymmetric) {
if let Asymmetric::Two(x0, _) = baa {
*x0 = 6;
}
}