【问题标题】:How do I write my own chainable iterator function in Rust? [duplicate]如何在 Rust 中编写自己的可链接迭代器函数? [复制]
【发布时间】:2019-06-20 18:22:13
【问题描述】:

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

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 实现它?有很多类型需要正确处理,所以为这个愚蠢的例子提供一个可行的解决方案会很有帮助。

【问题讨论】:

  • 了解这一点的最佳方法是查看任何内置迭代器函数的源代码。例如enumerate 是一个简单的。结构的实现是here。注意这个实现重写了很多方法,但是你只需要定义next
  • 这是一件值得学习的好东西,但我认为在这种特殊情况下这并不是“更干净”。它会引入很多代码,与按预期使用map 相比,这些代码并不是真正必要的。
  • @E4_net_or_something_like_that 感谢您的链接。我同意在这个简单的情况下它并不干净,但我需要一个简单的例子,以免问题变得广泛。

标签: rust iterator


【解决方案1】:

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

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

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

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));
}

【讨论】:

  • 请不要重复回答;这使得维护最新的知识库变得更加困难。
猜你喜欢
  • 1970-01-01
  • 2016-04-30
  • 2020-12-05
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 2016-06-26
  • 1970-01-01
相关资源
最近更新 更多