2015-09-04 38 views
5

許多庫允許您定義一個類型,該類型實現給定的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的關聯值。在處理程序中,您希望查找給定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已經借來的(通過self.map),當我們去訪問self.pool

一種可能的方法是將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); 
} 

這工作,但感覺有點克魯格-Y。它還介紹了爲每個方法調用移入和移出self的開銷。

這樣做的最好方法是什麼?

回答

11

要同時獲得對結構的不同部分的可變引用,請使用解構。示例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()); 
} 
+1

!!!謝謝!我知道解構,但不知道你可以用它來同時獲得可變引用。這是一個巨大的幫助! – zslayton

相關問題