迭代器

迭代器

Rust 的 for 循环实际上和 C 语言的循环语句是不同的,for 循环不过是 Rust 编译器提供的语法糖。首先,我们知道 Rust 有一个for循环能够依次对迭代器的任意元素进行访问,即:

for i in 1..10 {
    println!("{}", i);
}

这里我们知道,(1..10) 其本身是一个迭代器,我们能对这个迭代器调用 .next() 方法,因此,for 循环就能完整的遍历一个循环。在 Rust 中,迭代器共分为三个部分:迭代器、适配器、消费者。其中,迭代器本身提供了一个惰性的序列,适配器对这个序列进行诸如筛选、拼接、转换查找等操作,消费者则在前两者的基础上生成最后的数值集合。而对于Vec来说:

let values = vec![1,2,3];
for x in values {
    println!("{}", x);
}

在上面的代码中,我们并没有显式地将一个Vec转换成一个迭代器,那么它是如何工作的呢?现在就打开标准库翻 api 的同学可能发现了,Vec本身并没有实现 Iterator,也就是说,你无法对Vec本身调用 .next() 方法。但是,我们在搜索的时候,发现了Vec实现了 IntoIterator 的 trait。

其实,for循环真正循环的,并不是一个迭代器(Iterator),真正在这个语法糖里起作用的,是 IntoIterator 这个 trait。因此,上面的代码可以被展开成如下的等效代码:

let values = vec![1, 2, 3];

{
    let result = match IntoIterator::into_iter(values) {
        mut iter => loop {
            match iter.next() {
                Some(x) => { println!("{}", x); },
                None => break,
            }
        },
    };
    result
}

在这个代码里,我们首先对Vec调用 into_iter 来判断其是否能被转换成一个迭代器,如果能,则进行迭代。那么,迭代器自己怎么办?为此,Rust 在标准库里提供了一个实现:

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

也就是说,Rust 为所有的迭代器默认的实现了 IntoIterator,这个实现很简单,就是每次返回自己就好了。也就是说:任意一个 Iterator 都可以被用在 for 循环上!

无限迭代器

Rust 支持通过省略高位的形式生成一个无限长度的自增序列,即:

let inf_seq = (1..).into_iter();

不过不用担心这个无限增长的序列撑爆你的内存,占用你的 CPU,因为适配器的惰性的特性,它本身是安全的,除非你对这个序列进行collect或者fold

上一页