迭代器
迭代器
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
!