2015-07-08 15 views
7

लौटाती है मैं एक इटरेटर लौटने वाले कार्यों के साथ एक विशेषता बनाने की कोशिश कर रहा हूं।फ़ंक्शन के साथ विशेषता जो एक इटरेटर

मेरे सरल उदाहरण इस प्रकार है:

pub trait TraitA { 
    fn things(&self) -> Iterator<Item=&u8>; 
} 

fn foo<A: TraitA>(a: &A) { 
    for x in a.things() { } 
} 

कौन सा क्योंकि इटरेटर आकार प्रकार संकलन समय पर नहीं जाना जाता है काम नहीं करता।

+0

तो जैसे एक संबद्ध प्रकार नीचे जवाब में सुझाव का उपयोग कर (यह नहीं हो सकता है) उपयुक्त नहीं है, तो आप एक 'बॉक्स <इटरेटर > बजाय लौट सकते हैं'। लेकिन इसके लिए एक ढेर आवंटन की आवश्यकता होगी! – BurntSushi5

उत्तर

7

जंग के libstd इस में से एक कार्यान्वयन, विशेषता है IntoIterator

/// Conversion into an `Iterator` 
pub trait IntoIterator { 
    /// The type of the elements being iterated 
    type Item; 

    /// A container for iterating over elements of type `Item` 
    type IntoIter: Iterator<Item=Self::Item>; 

    /// Consumes `Self` and returns an iterator over it 
    fn into_iter(self) -> Self::IntoIter; 
} 

विशेषता वास्तव में व्यक्त करने के लिए दोनों "इटरेटर में" और "उधार इटरेटर" अर्थ विज्ञान सक्षम होने के लिए इस अजीब से-मूल्य (self) तैयार करने की है।

हैश मैप के IntoIterator कार्यान्वयन द्वारा दिखाया गया। (वे हैशैप के इटेटरेटर structs Iter और IntoIter का उपयोग करते हैं।) यहां दिलचस्प बात यह है कि "उधारकर्ता" उधार देने के लिए &HashMap<K, V, S> प्रकार के लिए विशेषता लागू की गई है।

impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> 
    where K: Eq + Hash, S: HashState 
{ 
    type Item = (&'a K, &'a V); 
    type IntoIter = Iter<'a, K, V>; 

    fn into_iter(self) -> Iter<'a, K, V> { 
     self.iter() 
    } 
} 

impl<K, V, S> IntoIterator for HashMap<K, V, S> 
    where K: Eq + Hash, S: HashState 
{ 
    type Item = (K, V); 
    type IntoIter = IntoIter<K, V>; 

    /// Creates a consuming iterator, that is, one that moves each key-value 
    /// pair out of the map in arbitrary order. The map cannot be used after 
    /// calling this. 
    fn into_iter(self) -> IntoIter<K, V> { 
     /* ... */ 
    } 
} 
1

एक और question के आधार पर, मैंने सोचा था कि सबसे अच्छा तरीका यह इतना की तरह, एक विशेषता प्रकार के रूप में इटरेटर परिभाषित करने के लिए किया जाएगा करने के लिए:

pub trait TraitA<'a> { 
    type I1: Iterator<Item=u8>; 
    type I2: Iterator<Item=&'a u8>; 

    fn iter_i1(&self) -> Self::I1; 
    fn iter_i2(&self) -> Self::I2; 
} 

fn foo<'a, A: TraitA<'a>>(a: &A) { 
    for x in a.iter_i1() { } 
    for x in a.iter_i2() { } 
} 
संबंधित मुद्दे