同时改变多个结构字段的最快惯用方法是啥?
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>
您的处理程序有一个从Token
到A
类型的项目的映射。 A
类型的每个项目可能已经或可能没有 B
类型的关联值。在处理程序中,您要查找给定Token
的A
值,如果它还没有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.map
和 self.pool
是不同的实体,但当我们访问 @987654342 时,借用检查器会抱怨 self
已经借用(通过 self.map
) @。
解决此问题的一种可能方法是将MyHandlerType
中的每个字段包装在Option<>
中。然后,在方法调用开始时,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 的嵌套映射中关联多个键/值的惯用方法是啥?