源代码
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}");
}
}
Run Code Online (Sandbox Code Playgroud)
输出
0
1
2
3
4
Run Code Online (Sandbox Code Playgroud)
就我个人而言,我理解每段代码想要做什么,但是我无法理解以下内容,可能是由于我对通用迭代器特征缺乏了解;
example.next方法被作为循环调用,直到None返回。代码如何知道这样做?广告 1。在 Rust 中“可迭代”意味着实现该Iterator特征。然而,有些东西可以变成迭代器,这是由另一个特质描述的IntoIterator。标准库提供了一个全面的实现:
impl<I: Iterator> IntoIterator for I { /* ... */}
Run Code Online (Sandbox Code Playgroud)
这意味着任何实现的类型都Iterator可以变成一种类型(它是 noop)。for循环设计用于与实现IntoIterator. 这就是为什么你可以这样写:
let mut v = vec![1, 2, 3, 4, 5];
for _ in &v {}
for _ in &mut v {}
for _ in v {}
Run Code Online (Sandbox Code Playgroud)
由于 types &Vec<T>,&mut Vec<T>并且Vec<T>都实现了IntoIteratorTrait。当然它们都变成了不同的迭代器类型,并且分别返回&T,&mut T和T。
广告 2 . 如前所述,for 循环可用于实现IntoIterator. 文档详细解释了它是如何工作的,但简而言之,循环for只是一个语法糖,可以转换此代码:
for x in xs {
todo!()
}
Run Code Online (Sandbox Code Playgroud)
变成这样的事情:
let mut xs_iter = xs.into_iter();
while let Some(x) = xs_iter.next() {
todo!()
}
Run Code Online (Sandbox Code Playgroud)
while循环也是语法糖,并loop通过break语句进行脱糖处理,但这与这里无关。
边注。我想这只是一个学习示例,它很棒,但是标准库中已经存在完全相同的迭代器std::ops::Range,因此如果需要,请使用它作为您的实际代码。