如何为迭代器编写具有生命周期的特征和实现?
How to write trait & impl with lifetimes for iterators?
我正在尝试了解如何为我自己的类型编写一个 trait
和一个 impl
来处理一些输入数据。我从一个简单的例子开始,我想用 trait Processor
处理输入 1, 2, 3, 4
。一个实现将跳过第一个元素并将所有剩余输入加倍。因此它应该看起来像这样:
trait Processor {} // TBD
struct SkipOneTimesTwo;
impl Processor for SkipOneTimesTwo {} // TBD
let numbers = vec![1, 2, 3, 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()
instead of 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());
}
我正在尝试了解如何为我自己的类型编写一个 trait
和一个 impl
来处理一些输入数据。我从一个简单的例子开始,我想用 trait Processor
处理输入 1, 2, 3, 4
。一个实现将跳过第一个元素并将所有剩余输入加倍。因此它应该看起来像这样:
trait Processor {} // TBD
struct SkipOneTimesTwo;
impl Processor for SkipOneTimesTwo {} // TBD
let numbers = vec![1, 2, 3, 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()
instead of 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());
}