简体   繁体   English

具有返回迭代器的函数的trait

[英]trait with functions that return an iterator

I'm trying to build a trait with functions that return an iterator. 我正在尝试使用返回迭代器的函数构建一个特征。

My simple example looks like this: 我的简单示例如下所示:

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

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

Which does not work because the Iterator size type is not known at compile time. 哪个不起作用,因为在编译时不知道Iterator大小类型。

Rust's libstd has one implementation of this, the trait IntoIterator . Rust的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;
}

The trait has this peculiar by-value ( self ) formulation exactly to be able to express both “into iterator” and “borrow iterator” semantics. 该特征具有这种特殊的按值( self )公式,完全能够表达“迭代器”和“借用迭代器”语义。

Demonstrated by HashMap's IntoIterator implementations. 由HashMap的IntoIterator实现演示。 (They use the hashmap's iterator structs Iter and IntoIter .) What's interesting here is that the trait is implemented for the type &HashMap<K, V, S> to express the “borrow iterator”. (他们使用hashmap的迭代器结构IterIntoIter 。)这里有趣的是,为类型&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> {
        /* ... */
    }
}

Based on another question , I thought that the best way to do it would be to define the Iterator as a trait type, like so: 基于另一个问题 ,我认为最好的方法是将Iterator定义为特征类型,如下所示:

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() { }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM