Rust 的迭代器 III

迭代器的特性

技术
技术Rust标准库编程语言特性迭代器

2026-03-28

见识过迭代器的一众用法后,是时候针对某些使用过程中的陷阱进行特别说明了。它们或多或少都与迭代器的特性有所关联。

迭代器的特性

惰性

迭代器以及迭代器适配器都是惰性的。这意味着仅仅创建一个迭代器并不会做太多事情。在实际调用 next 之前什么都不会真正发生。如果只是为了某些“无关痛痒”的操作而创建迭代器,那么程序的反应可能让人困惑不解。例如 map 方法的例子:

let v = vec![1, 2, 3, 4, 5];
v.iter().map(|x| println!("{x}"));

这段代码不会打印任何值,因为我们只创建了一个迭代器却不使用它。编译器会针对这种行为发出警告:

warning: unused result that must be used: iterators are lazy and
do nothing unless consumed

更好的写法是使用 for 循环或调用 for_each 方法:

let v = vec![1, 2, 3, 4, 5];

v.iter().for_each(|x| println!("{x}"));
// 或者
for x in &v {
    println!("{x}");
}

无穷性

迭代器的元素不一定是有限的。例如,一个无上限的区间就是一个无限迭代器:

let numbers = 0..;

通常使用 take 迭代器适配器将无限迭代器转换为有限迭代器:

let numbers = 0..;
let five_numbers = numbers.take(5);

for number in five_numbers {
    println!("{number}");
}

反过来的话,前面提到的 cycle 方法能将有限迭代器转换为无限迭代器。

要注意:即使那些在数学上可以在有限时间内确定结果的方法,在无限迭代器上也可能永远不会终止。具体来说,像 min 这样的方法,在一般情况下需要遍历迭代器中的每个元素,对于任何无限迭代器很可能就无法成功返回。

let ones = std::iter::repeat(1);
let least = ones.min().unwrap();
// `ones.min()` 导致无限进行遍历
// 所以下面的语句永远不会到达:
println!("The smallest number one is {least}.");

参考资料