实现自定义迭代器特征

ken*_*esu 2 iterator rust

源代码

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)

就我个人而言,我理解每段代码想要做什么,但是我无法理解以下内容,可能是由于我对通用迭代器特征缺乏了解;

  1. 为结构体实现迭代器特征是否会自动生成可迭代的数据类型?在这种情况下,我不知道为什么可以在example.
  2. 看起来该next方法被作为循环调用,直到None返回。代码如何知道这样做?

Ale*_*uze 6

广告 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 TT

广告 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,因此如果需要,请使用它作为您的实际代码。