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

Posted

技术标签:

【中文标题】同时改变多个结构字段的最快惯用方法是啥?【英文标题】:What's the fastest idiomatic way to mutate multiple struct fields at the same time?同时改变多个结构字段的最快惯用方法是什么? 【发布时间】:2015-09-04 17:50:58 【问题描述】:

许多库允许您定义实现给定trait 的类型以用作回调处理程序。这要求您将处理事件所需的所有数据集中在一个数据类型中,这使得借用变得复杂。

例如,mio 允许您实现 Handler 并在您 run the EventLoop 时提供您的结构。考虑一个具有这些平凡数据类型的示例:

struct A 
  pub b: Option<B>
;

struct B;

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

您的处理程序有一个从TokenA 类型的项目的映射。 A 类型的每个项目可能已经或可能没有 B 类型的关联值。在处理程序中,您要查找给定TokenA 值,如果它还没有B 值,则从处理程序的Pool&lt;B&gt; 中取出一个。

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 是不同的实体,但当我们访问 @987654342 时,借用检查器会抱怨 self 已经借用(通过 self.map) @。

解决此问题的一种可能方法是将MyHandlerType 中的每个字段包装在Option&lt;&gt; 中。然后,在方法调用开始时,take() 那些来自self 的值并在调用结束时恢复它们:

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】:

要同时获取对结构不同部分的可变引用,请使用解构。示例here。

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());

【讨论】:

!!!谢谢!我知道解构,但不知道你可以用它来同时获得可变引用。这是一个巨大的帮助!

以上是关于同时改变多个结构字段的最快惯用方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

一次循环遍历 Javascript 数组多个元素的惯用方法是啥?

将 2x4 64b 结构的第一行加载到 AVX2 的 256b 寄存器中的最快方法是啥?

在 Clojure 的嵌套映射中关联多个键/值的惯用方法是啥?

在 html5 下动画多个精灵的最快方法是啥?

处理在多个 for 循环中声明的变量的最惯用方法是啥? [关闭]

使用 Scala 根据 RDD 中的多个键列对值进行分组的最快方法是啥? [复制]