如何在嵌套匹配语句中多次访问可变向量?

How to access a mutable vector multiple times in nested match statements?

我有以下代码:

enum T {
    A(bool),
    B(u8),
}

fn main() {
    let mut a = vec![T::A(true), T::B(42)];
    match a[0] {
        T::A(value) => println!("A: {}", value),
        T::B(ref mut b) => {
            match a[1] {
                T::A(value) => println!("One more A: {}", value),
                T::B(ref mut value) => *value += 1,
            }
            *b += 1
        }
    }
}

编译器抱怨:

error[E0499]: cannot borrow `a` as mutable more than once at a time
  --> src/main.rs:11:19
   |
8  |     match a[0] {
   |           - first mutable borrow occurs here
...
11 |             match a[1] {
   |                   ^ second mutable borrow occurs here
...
17 |     }
   |     - first borrow ends here

我知道问题是因为我有两个对 a 的可变引用,但我找不到解决方案。

如果您愿意为第一场比赛准备一份副本,您可以这样做:

#[derive(Debug, Copy, Clone)]
enum T {
    A(bool),
    B(u8),
}

fn main() {
    let mut a = vec![T::A(true), T::B(42)];
    let first = a[0]; // make a copy
    match first {
        // match on the copy
        T::A(value) => println!("A: {}", value),
        T::B(b) => {
            match a[1] {
                T::A(value) => println!("One more A: {}", value),
                T::B(ref mut value) => *value += 1,
            }
            a[0] = T::B(b + 1) // then update the vector
        }
    }
    println!("{:?}", a); // the original didn't get split
}

如果您的类型是 Clone 而不是 Copy,这也适用于 Clone。另一种选择是按照问题评论中的建议使用 split_at_mut()

如果你使用夜间编译器,你可以使用

  • 特征 slice_patterns 匹配切片
  • split_at_mut 如评论中所建议

代码:

#![feature(slice_patterns)]

enum T {
    A(bool),
    B(u8),
}

fn main() {
    let mut a = vec![T::A(true), T::B(42)];
    match a.split_at_mut(0) {
        (&mut [T::A(value)], _) => println!("A: {}", value),
        (&mut [T::B(ref mut b)], ref mut rest) => {
            match *rest {
                &mut [T::A(value)] => println!("One more A: {}", value),
                &mut [T::B(ref mut value)] => *value += 1,
                _ => (), // mandatory, because we match against slice
            }
            *b += 1
        }
        _ => (), // mandatory, because we match against slice
    }
}

这段代码可读性不是很好,因为一切都是参考,因为您需要详尽地涵盖模式,但它满足您的要求。