2015-09-04 4 views
5

कई पुस्तकालय आपको एक प्रकार को परिभाषित करने की अनुमति देते हैं जो किसी दिए गए trait को कॉलबैक हैंडलर के रूप में उपयोग करने के लिए लागू करता है। इसके लिए आपको एक ही डेटा प्रकार में एक साथ ईवेंट को संभालने के लिए आवश्यक सभी डेटा को लंप करने की आवश्यकता होती है, जो उधार को जटिल बनाता है।एक साथ कई संरचना क्षेत्रों को बदलने के लिए सबसे तेज़ बेवकूफ तरीका क्या है?

उदाहरण के लिए, mio आपको Handler लागू करने और run the EventLoop पर अपनी संरचना प्रदान करने की अनुमति देता है। इन trivialized डेटा प्रकार के साथ एक उदाहरण पर विचार करें:

struct A { 
    pub b: Option<B> 
}; 

struct B; 

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

आपका हैंडलर प्रकार A के आइटम के लिए Token से एक नक्शा है। 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 अलग संस्थाओं को देखने के लिए सहज संभव है, उधार चेकर शिकायत है कि self पहले से ही लिया गया है (self.map के माध्यम से) जब हम self.pool उपयोग करने के लिए जाना।

Option<> में MyHandlerType में प्रत्येक फ़ील्ड को लपेटना होगा। फिर, विधि कॉल के शुरू में, 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

संरचना के विभिन्न हिस्सों में एक साथ परिवर्तनीय संदर्भ प्राप्त करने के लिए, विनाशकारी का उपयोग करें। उदाहरण ।

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

संबंधित मुद्दे