源代码
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
就我个人而言,我理解每段代码试图做什么,但我很难理解以下内容,可能是因为我对通用迭代器特性缺乏理解;
- 实现结构的Iterator特性会自动生成可迭代的数据类型吗?在这种情况下,我不知道为什么在
example
上可以使用for循环 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 T
和T
。
广告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
完全相同的迭代器,所以如果需要,请使用它作为实际代码