【问题标题】:How to access a mutable vector multiple times in nested match statements?如何在嵌套匹配语句中多次访问可变向量?
【发布时间】:2018-01-18 20:30:26
【问题描述】:

我有以下代码:

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 的可变引用,但我找不到解决方案。

【问题讨论】:

标签: rust pattern-matching borrow-checker


【解决方案1】:

如果您愿意在第一场比赛中获得副本,您可以这样做:

#[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。另一种选择是使用问题 cmets 中建议的split_at_mut()

【讨论】:

    【解决方案2】:

    如果你使用 nightly 编译器,你可以使用

    • slice_patterns 与切片匹配的功能
    • split_at_mut 在 cmets 中建议

    代码:

    #![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
        }
    }
    

    这段代码不是超级可读的,因为所有内容都是参考,并且因为您需要详尽地涵盖模式,但它满足您的要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-26
      • 1970-01-01
      • 2015-08-10
      • 2023-02-07
      • 2021-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多