如何在Rust中编写自己的可链接迭代器函数?

时间:2019-01-27 16:30:10

标签: rust iterator

假设我要在数字迭代器中将每个值加倍。我可以这样做:

vec![1, 2, 3]
    .into_iter()
    .map(|x| x * 2)
    .for_each(|x| println!("{}", x)); //Prints 2, 4, 6.

要获得更简洁的代码,我希望这样做:

vec![1, 2, 3]
    .into_iter()
    .double() //I need to implement this.
    .for_each(|x| println!("{}", x));

如何编写自己的可链接迭代器函数,例如本示例中的double?我想我将不得不创建一个接口并为Iterator实现它?有很多正确的类型,因此为这个愚蠢的示例提供可行的解决方案将很有帮助。

1 个答案:

答案 0 :(得分:1)

首先,您必须创建一个新类型来实现您的迭代器。最简单的方法是包装您要定位的类型的迭代器:

struct Double<T: ?Sized> {
    inner: T,
}

现在,如果内部类型Iterator具有正确的类型,则只需为此类型实现T特征。像这样:

impl<T> Iterator for Double<T>
where T: Iterator<Item = i32> {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        self.inner.next().map(|x| 2*x)
    }
}

就是这样!您只需要添加一个Double构造函数。最符合人体工程学的解决方案是扩展Iterator。像这样:

trait Doubler : Iterator<Item = i32> {
    fn into_double(self) -> Double<Self>;
}

impl<T> Doubler for T
where T: Iterator<Item = i32> {
    fn into_double(self) -> Double<Self> {
        Double { inner: self }
    }
}

用法示例(playground):

fn main() {
    vec![1, 2, 3]
        .into_iter()
        .into_double()
        .for_each(|x| println!("{}", x));
}