什么是同时改变多个结构体字段的最快惯用方法?

6
Many libraries enable you to define a type that implements a specific trait to serve as a callback handler. This necessitates combining all the data required to handle an event into a single data type, which complicates borrowing.
For example, with mio, you can implement Handler and provide your struct when you run the EventLoop. Consider this example with simplified data types:
struct A {
  pub b: Option<B>
};

struct B;

struct MyHandlerType {
  pub map: BTreeMap<Token, A>,
  pub pool: Pool<B>
}

您的处理程序有一个从Token到类型为A的项目的映射。每个类型为A的项目可能已经具有或没有关联的类型B的值。在处理程序中,您希望查找给定TokenA值,并且如果它还没有B值,则从处理程序的Pool<B>中获取一个。

impl Handler for MyHandlerType {
    fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>, 
             token: Token, events: EventSet) {
       let a : &mut A = self.map.get_mut(token).unwrap();
       let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
       // Continue working with `a` and `b`
       // ...
    }
}

在这种排列中,即使直观上可以看到self.mapself.pool是不同的实体,但借用检查器会抱怨当我们去访问self.poolself已经被借用(通过self.map)。
一种可能的方法是将MyHandlerType中的每个字段包装在Option<>中。然后,在方法调用开始时,从selftake()这些值,并在调用结束时恢复它们。
struct MyHandlerType {
  // Wrap these fields in `Option`
  pub map: Option<BTreeMap<Token, A>>,
  pub pool: Option<Pool<B>>
}
// ...

fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>, 
         token: Token, events: EventSet) {
  // Move these values out of `self`
  let map = self.map.take().unwrap();
  let pool = self.pool.take().unwrap();

  let a : &mut A = self.map.get_mut(token).unwrap();
  let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
  // Continue working with `a` and `b`
  // ...

  // Restore these values to `self`
  self.map = Some(map);
  self.pool = Some(pool);
}

这个方法可行但感觉有些笨拙。它还会引入每个方法调用中在self中移动值的开销。
有什么更好的方法吗?
1个回答

14

使用解构来获取对结构体不同部分的同时可变引用。示例在这里

struct Pair {
    x: Vec<u32>,
    y: Vec<u32>,
}

impl Pair {
    fn test(&mut self) -> usize {
        let Pair{ ref mut x, ref mut y } = *self;
        // Both references coexist now
        return x.len() + y.len();
    }
}

fn main() {
    let mut nums = Pair {
        x: vec![1, 2, 3],
        y: vec![4, 5, 6, 7],
    };
    println!("{}", nums.test());
}

1
谢谢!我知道解构,但不知道可以使用它来获取同时可变的引用。这对我帮助很大! - zslayton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接