2015-08-22 8 views
6

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

pub fn print_strings(strings: Vec<String>) { 
    for val in strings.iter() { 
     println!("{}", val); 
    } 
} 

जाहिर है इस छोटे से गिर जाता है अगर मैं उपयोग करने के लिए है कि एक HashSet या HashMap साथ चाहते हैं।

use std::collections::*; 

fn main() { 
    let strings = vec!("Foo", "Bar"); 

    let mut more_strings = HashMap::new(); 
    more_strings.insert("foo", "bar"); 
    more_strings.insert("bar", "foo"); 

    print_strings(&strings.iter()); 
    print_strings(&more_strings.values()) 
} 

fn print_strings(strings: &Iterator<Item=&str>) { 
    for val in strings { 
     println!("{}", val); 
    } 
} 

Playpen (भी लंबा संकलक त्रुटि देखने पर)

http://is.gd/EYIK11

दुर्भाग्य से, यह या तो चाल करने के लिए प्रतीत नहीं होता:

तो, मैं इस कोशिश की। मैं क्या खो रहा हूँ?

+0

कृपया त्रुटि संदेश शामिल करें। यह आपको बताता है कि आपके कार्यान्वयन में क्या गलत है।आप समीक्षा कर सकते हैं कि आपके पास इटरेटर के लिए 'इटरेटर :: आइटम' किस प्रकार का है। – Shepmaster

+0

मुझे नहीं लगता कि यह एक अच्छा विचार है क्योंकि यह काफी लंबा है। आप पूरे कंपाइलर त्रुटि आउटपुट को देखने के लिए प्लेपेन लिंक पर क्लिक कर सकते हैं। – Christoph

+0

जब आप 'Vec 'पर' .iter() 'को कॉल करते हैं, तो आपको' Iterator 'मिलता है। इसलिए जब आप 'Vec <&str> 'पर' .iter() 'को कॉल करते हैं, तो आपको' Iterator 'मिलता है, न कि' Iterator '। आपको 'Iterator' के लिए' .cloned() 'विधि को देखना चाहिए, इससे आपकी समस्या का समाधान करने में मदद मिलनी चाहिए। – Adrian

उत्तर

7

और भी बेहतर, आप (सुधार के लिए कुडोस Shepmaster।)

fn print_strings<Iterable>(strings: Iterable) 
    where Iterable: IntoIterator, 
      Iterable::Item: AsRef<str> 
{ 
    for val in strings { 
     println!("{}", val.as_ref()); 
    } 
} 

कर सकते हैं

इसका मतलब यह है कि आप गतिशील प्रेषण या ठोस iterator या के लिए &mut Iterator रों के साथ इस कॉल कर सकते हैं स्थैतिक प्रेषण के लिए संग्रह प्रकार। इसके अलावा, इटरेटर प्रकार कुछ भी हो सकता है जिसे आसानी से &str में परिवर्तित किया जा सकता है, जिसमें &str, &&str और यहां तक ​​कि String तक सीमित नहीं है।

print_strings(&strings); 
print_strings(strings.iter().map(|s| s.to_owned())); 
print_strings(vec![&&&&"xyz"]); 
print_strings(strings); 
print_strings(more_strings.values()); 
4

जब आप .iter() पर Vec<T> पर कॉल करते हैं, तो आपको Iterator<Item=&T> मिलता है। तो जब आप .iter() को Vec<&str> पर कॉल करते हैं, तो आपको Iterator<Item=&&str> मिलता है, Iterator<Item=&str> नहीं। आपको Iterator के लिए .cloned() विधि को देखना चाहिए, इसे आपकी समस्या का समाधान करने में मदद करनी चाहिए।

इसके अलावा, ध्यान दें कि एक पुनरावर्तक के माध्यम से पुनरावृत्त करने के लिए, आप इसे उत्परिवर्तित करने में सक्षम होना चाहिए (या तो इसके इटरेटर का मालिक हो या इसके लिए एक उत्परिवर्तनीय संदर्भ हो)। तो बस इसके लिए एक अपरिवर्तनीय संदर्भ होने के क्रम में बेकार है। मैं संदर्भ द्वारा इसे पारित करने के बजाय iterator मान को print_strings में ले जाने की अनुशंसा करता हूं। यदि आप इसके लिए विशेषता वस्तुओं का उपयोग करना चाहते हैं, तो आप Box का उपयोग करके ऐसा कर सकते हैं, लेकिन प्रिंट जेस्ट्रिंग को सामान्य कार्य करना आसान हो सकता है।

4

playpen
तो पहली बात यह है कि आप Iterator<Item=&str> की उम्मीद कर रहे है, लेकिन यह वास्तव में Iterator<Item=&&str> है।
फिर, आप .iter() पर कॉल करने का प्रयास कर रहे हैं, लेकिन Iterator में यह विधि नहीं है। आप बस .iter() कॉल को हटा सकते हैं और प्राप्त (और ऑप्टिकल फाइबर केबल भेज) काम कर for पाश पाने के लिए क्रम में &mut Iterator<...> (for पाश कुछ, को लागू करने वाली IntoIterator जरूरत है, और &mut Iterator कि बात है)।
जीवनकाल जोड़ें और आप सब तैयार हैं! :)
इसके अलावा, मैं स्थैतिक प्रेषण का उपयोग करने की सिफारिश कर रहा हूं। आप इसे प्रदान किए गए उदाहरण में देख सकते हैं।

+0

ठीक है, वह playpen इसे पूरी तरह से साफ़ करता है। स्थिर प्रेषण के संबंध में, मैं उदाहरण के लिए कुछ कीस्ट्रोक सहेज रहा था: पी – Christoph

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