2016-07-26 4 views
5

मेरे पास डिस्क पर संग्रह डंप किए गए हैं। अनुरोध किए जाने पर, इन संग्रहों को पुनर्प्राप्त किया जाना चाहिए (कोई समस्या नहीं) और iterator इसके लिए बनाया जाना चाहिए जो पुनर्प्राप्त मूल्यों के संदर्भ देता है।Iterate। जैसे ही इटरेटर गिरा दिया जाता है, इसे छोड़ दें

iterator के बाद गिरा दिया गया है, मुझे अब संग्रह की आवश्यकता नहीं है। मैं इसे भी छोड़ना चाहता हूं।

क्या मैं अब तक की कोशिश की है:

  1. Iterator संग्रह का मालिक है। यह मेरे लिए सबसे ज्यादा समझ में आया, लेकिन यह संभव नहीं है; मुझे पूरा यकीन नहीं है क्यों। कुछ कहते हैं कि Iteratornext के लिए लक्षण 'विधि हस्ताक्षर समस्या है। (example)

  2. संदर्भ गिनती: Retriever एक Rc<Vec<usize>> देता है। मैं मालिकों के मालिक के समान समस्याओं में भाग गया। (example)

  3. प्रतिद्वंद्वी को संग्रह का स्वामी होने और इसके संदर्भ को सौंपने देना। मैंने इंटीरियर म्यूटेबिलिटी (RefCell<HashMap>) के साथ रेट्रिवर को लागू करने की कोशिश की, लेकिन मैं काफी लंबे समय तक HashMap में संदर्भ वापस नहीं कर सकता।

मुझे इसके साथ दो मूल संभावनाएं दिखाई देती हैं।

  1. प्रतिद्वंद्वी स्वामित्व स्थानांतरित करता है। फिर Iterator को डेटा का स्वामित्व करने की आवश्यकता होगी। कुछ पंक्तियों में:

    use std::slice::Iter; 
    
    fn retrieve(id: usize) -> Vec<usize> { 
        //Create Data out of the blue (or disk, or memory, or network. I dont care) 
        //Move the data out. Transfer ownership 
        let data = vec![0, 1, 2, 3]; 
        data 
    } 
    
    fn consume_iterator<'a, TIterator: Iterator<Item=&'a usize>>(iterator: TIterator) { 
        for i in iterator { 
         println!("{}", i); 
        } 
    } 
    
    fn handler<'a>(id: usize) -> Iter<'a, usize> { 
        //handle_request now owns the vector. 
        //I now want to build an owning iterator.. 
        //This does of course not compile as vector will be dropped at the end of this method 
        retrieve(id).iter() 
    } 
    
    fn main() { 
        consume_iterator(handler(0)) 
    } 
    
  2. प्रतिद्वंद्वी संग्रह का मालिक है। लेकिन फिर दो नई समस्याएं उत्पन्न होती हैं:

    1. इटरेटर रेंज से बाहर होने पर मैं डेटा को कैसे छोड़ सकता हूं?
    2. मैं उधारकर्ता-चेकर को कैसे बताऊं कि मैं लंबे समय तक संग्रह का मालिक बनूंगा?

    use std::cell::{Ref, RefCell}; 
    
    struct Retriever { 
        //Own the data. But I want it to be dropped as soon as the references to it go out of scope. 
        data: RefCell<Vec<usize>> 
    } 
    
    impl Retriever{ 
    
        fn retrieve<'a>(&'a self, id: usize) -> Ref<'a, Vec<usize>> { 
         //Create Data out of the blue (or disk, or memory, or network. I dont care) 
         //Now data can be stored internally and a referece to it can be supplied. 
         let mut data = self.data.borrow_mut(); 
         *data = vec![0, 1, 2, 3]; 
         self.data.borrow() 
        } 
    
    } 
    
    fn consume_iterator<'a, TIterator: Iterator<Item=&'a usize>>(iterator: TIterator) { 
        for i in iterator { 
         println!("{}", i); 
        } 
    } 
    
    
    fn handler<'a>(ret: &'a Retriever, id: usize) -> IterWrapper<'a> { 
        //andle_request now has a reference to the collection 
        //So just call iter()? Nope. Lifetime issues. 
        ret.retrieve(id).iter()   
    } 
    
    fn main() { 
        let retriever = Retriever{data: RefCell::new(Vec::new())}; 
        consume_iterator(handler(&retriever, 0)) 
    } 
    

मैं थोड़ा यहाँ खो लग रहा है और कुछ स्पष्ट अनदेखी कर रहा हूँ।

+1

मुझे लगता है कि आपको ['std :: vec :: IntoIter'] की आवश्यकता है (https://doc.rust-lang.org/stable/std/vec/struct.IntoIter.html): https: // play। rust-lang.org/?gist=0e6c171c08fc7a314c44ac98f3dd398e&version=stable&backtrace=0 लेकिन फिर आप इसके बजाय सीधे 'IntoIter' का उपयोग भी कर सकते हैं। – Dogbert

+0

जबकि यह संकलित होगा, 'IntoIter' मानों को ले जाता है। 'Iterator' के प्राप्त होने वाले मान मानों के संदर्भों की अपेक्षा करते हैं। मैं – JDemler

+3

के अनुसार अपना प्रश्न अपडेट करूंगा, मुझे डर है कि आपने किसी भी तरह [XY समस्या] में भाग लिया है (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) ... क्यों यदि आपको मूल्यों की आवश्यकता नहीं है, तो क्या आपको मूल्यों के संदर्भों की आवश्यकता है? उधार लेने का पूरा बिंदु इसलिए है कि आप स्वामित्व रखते हैं, लेकिन स्पष्ट रूप से आप स्वामित्व रखना नहीं चाहते हैं। –

उत्तर

1

मैं अब अंत में एक अपेक्षाकृत statisfying समाधान को लागू करने में सक्षम था। यहां एक उदाहरण के रूप में एक struct है कि दोनों का मालिक है और अधिक पुनरावृति कर सकते हैं के कार्यान्वयन है एक Arc<Vec<T>>:

pub struct ArcIter<T> { 
    data: Arc<Vec<T>>, 
    pos: Cell<usize>, 
} 

impl<'a, T: 'a> OwningIterator<'a> for ArcIter<T> { 
    type Item = &'a T; 

    fn next(&'a self) -> Option<Self::Item> { 
     if self.pos.get() < self.data.len() { 
      self.pos.set(self.pos.get() + 1); 
      return Some(&self.data[self.pos.get() - 1]); 
     } 
     None 
    } 
} 

जैसा कि मैंने इंटरफेस के पीछे iterators इस तरह छिपाने के लिए और उपयोगकर्ता केवल "असली" iterators संभालने दें करने में सक्षम था मुझे लगता है कि यह मानक से एक स्वीकार्य विचलन है।

उन सभी लोगों के लिए धन्यवाद जिन्होंने विचारों के साथ योगदान दिया जिसने अंततः मुझे उस समाधान को खोजने में मदद की।

4

Iterator संग्रह का मालिक है। [या के माध्यम से संयुक्त स्वामित्व संदर्भ गिनती]

ContainerIterator { 
    data: data, 
    iter: data.iter(), 
} 

नहीं, आप cannot have a value and a reference to that value in the same struct

प्रतिद्वंद्वी को संग्रह का स्वामी होने और इसके संदर्भ को सौंपने देना।

नहीं, आप cannot return references to items owned by the iterator

रूप टिप्पणीकर्ताओं कहा है, इटरेटर करने के लिए आइटम का स्वामित्व स्थानांतरित करें और फिर उन्हें वितरित करने के लिए दोहराया मूल्यों के रूप में IntoIter का उपयोग करें:

use std::vec::IntoIter; 

struct ContainerIterator { 
    iter: IntoIter<usize>, 
} 

impl Iterator for ContainerIterator { 
    type Item = usize; 

    fn next(&mut self) -> Option<Self::Item> { 
     self.iter.next() 
    } 
} 

fn main() { 
    let data = vec![0, 1, 2, 3]; 
    let cont = ContainerIterator { iter: data.into_iter() }; 

    for x in cont { 
     println!("Hi {}", x) 
    } 
} 

आप चाहिए वापसी के संदर्भ ... तो आप की जरूरत है उस चीज को रखने के लिए जो पूरे समय के आसपास उनका मालिक है कि सभी संदर्भ आसपास हो सकते हैं।

इटरेटर रेंज से बाहर होने पर मैं डेटा को कैसे छोड़ सकता हूं?

मूल्य का उपयोग नहीं करके किसी भी अधिक:

fn main() { 
    { 
     let loaded_from_disk = vec![0, 1, 2, 3]; 
     for i in &loaded_from_disk { 
      println!("{}", i) 
     } 
     // loaded_from_disk goes out of scope and is dropped. Nothing to *do*, per se. 
    } 
} 

मैं कैसे उधार-चेकर है कि मैं काफी देर तक संग्रह स्वामी होगा बताऊँ?

लंबे समय तक संग्रह का मालिकाना। जंगली इलुमिनेटी उधार चेकर के साथ उपयोग करने के लिए कोई गुप्त हैंडशेक नहीं है। कोड को केवल संरचित करने की आवश्यकता है जैसे कि उधार ली गई वस्तु अमान्य नहीं होती है जबकि उधार बकाया है। आप इसे स्थानांतरित नहीं कर सकते (स्मृति पता बदल रहे हैं) या इसे छोड़ दें (स्मृति पता बदलना)। Cell रों अंदर

iterators की अस्थिरता छिपाना::

pub trait OwningIterator<'a> { 
    type Item; 
    fn next(&'a self) -> Option<Self::Item>; 
} 

एक struct अब एक Cell घ स्थिति उत्परिवर्तन के बिना यात्रा की अनुमति देने की जरूरत है

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