实现自定义迭代器Trait



源代码

pub struct Iterating_ex {
start: u32,
end: u32,
}
impl Iterator for Iterating_ex {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.start >= self.end {
None
} else {
let result = Some(self.start);
self.start += 1;
result
}
}
}
fn main() {
let example = Iterating_ex {
start: 0,
end: 5,
};
for i in example {
println!("{i}");
}
}

输出

0
1
2
3
4

就我个人而言,我理解每段代码试图做什么,但我很难理解以下内容,可能是因为我对通用迭代器特性缺乏理解;

  1. 实现结构的Iterator特性会自动生成可迭代的数据类型吗?在这种情况下,我不知道为什么在example上可以使用for循环
  2. next方法似乎是作为一个循环调用的,直到返回None为止。代码是如何知道这样做的

Ad 1。成为";可迭代的";在锈中意味着实现CCD_ 4特性。然而,有些东西可以变成迭代器,这由另一个特性IntoIterator来描述。标准库提供了一揽子实现:

impl<I: Iterator> IntoIterator for I { /* ... */}

这意味着任何实现Iterator的类型都可以变成一个(它是noop(。for循环被设计为与实现IntoIterator的类型一起工作。这就是为什么你可以写例如:

let mut v = vec![1, 2, 3, 4, 5];
for _ in &v {}
for _ in &mut v {}
for _ in v {}

由于类型&Vec<T>&mut Vec<T>Vec<T>都实现了IntoIterator特性。当然,它们都被转换成不同的迭代器类型,并分别返回&T&mut TT

广告2。如前所述,循环可以用于实现IntoIterator的类型。文档详细解释了它是如何工作的,但简而言之,for循环只是一个语法糖,它可以转换以下代码:

for x in xs {
todo!()
}

变成这样:

let mut xs_iter = xs.into_iter();
while let Some(x) = xs_iter.next() {
todo!()
}

while循环也是语法糖,并使用break语句将其解糖为loop,但这与此处无关。

旁注。我想这只是一个学习示例,它很好,但标准库中已经存在与std::ops::Range完全相同的迭代器,所以如果需要,请使用它作为实际代码

最新更新