微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何为迭代器编写具有生命周期的特征和实现?

如何解决如何为迭代器编写具有生命周期的特征和实现?

我试图了解如何为我自己的类型编写一个 trait一个 impl 来处理一些输入数据。我从一个简单的例子开始,我想用 1,2,3,4 处理输入 trait Processor一个实现将跳过第一个元素并将所有剩余的输入加倍。因此,它应该如下所示:

trait Processor {} // TBD

struct SkipOneTimesTwo;
impl Processor for SkipOneTimesTwo {} // TBD

let numbers = vec![1,4];
let it = numbers.iter();
let it = Box::new(it);

let proc = SkipOneTimesTwo;
let four_to_eight = proc.process(it);
assert_eq!(Some(4),four_to_eight.next());
assert_eq!(Some(6),four_to_eight.next());
assert_eq!(Some(8),four_to_eight.next());
assert_eq!(None,four_to_eight.next());

所以我的假设是我的特征和相应的实现看起来像这样:

trait Processor {
    // Arbitrarily convert from `i32` to `u32`
    fn process(&self,it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>>;
}

struct SkipOneTimesTwo;
impl Processor for SkipOneTimesTwo {
    fn process(&self,it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>> {
        let p = it.skip(1).map(|i| 2 * (i as u32));
        Box::new(p)
    }
}

代码无法按原样运行。我收到以下错误

7 |     let four_to_eight = proc.process(it);
  |                                      ^^ expected `i32`,found reference
  |
  = note:   expected type `i32`
          found reference `&{integer}`
  = note: required for the cast to the object type `dyn Iterator<Item = i32>`

如果我的输入数据非常大,我不希望整个数据集都保存在内存中(使用 Iterator 的全部意义),所以我假设使用 Iterator<T> 应该流式传输数据从原始输入源开始,直到最终聚合或以其他方式处理。然而,我不知道这意味着什么,我需要在这里注释哪些生命周期。

最终,我的 Processor 可能会保存来自输入的一些中间数据(例如,用于运行平均值计算),因此我可能必须在结构上指定生命周期。

处理一些编译器错误,我尝试将 'a'static'_ 生命周期添加到我的 dyn Iterator<...>,但我不太明白了解如何传递输入迭代器并懒惰地修改值。

这甚至是一种合理的方法吗?我可以输入Iterator<Item = i32>可能存储在我的结构和impl Iterator<Item = u32> for SkipOneTimesTwo,但后来我大概会失去一些能够抽象的,以绕过Processor特质。

解决方法

Rust 中的所有迭代器都是惰性的。此外,您不需要使用生命周期,只需使用 into_iter() 而不是 iter() 并且您的代码会编译:

trait Processor {
    fn process(&self,it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>>;
}

struct SkipOneTimesTwo;

impl Processor for SkipOneTimesTwo {
    fn process(&self,it: Box<dyn Iterator<Item = i32>>) -> Box<dyn Iterator<Item = u32>> {
        let p = it.skip(1).map(|i| 2 * (i as u32));
        Box::new(p)
    }
}

fn main() {
    let numbers = vec![1,2,3,4];
    let it = numbers.into_iter(); // only change here
    let it = Box::new(it);
    
    let pro = SkipOneTimesTwo;
    let mut four_to_eight = pro.process(it);
    assert_eq!(Some(4),four_to_eight.next());
    assert_eq!(Some(6),four_to_eight.next());
    assert_eq!(Some(8),four_to_eight.next());
    assert_eq!(None,four_to_eight.next());
}

playground

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。