本页目录
Iterator 与闭包
Iterator 是 Rust 最成功的抽象——map/filter/chain 等 adaptor 是惰性的(不调用不执行),编译后内联展开为手写循环等效的机器码(zero-cost)。Fn/FnMut/FnOnce 三种闭包 trait 对应三种捕获方式,collect 把迭代器收拢为容器——链式操作从 readable 到 zero-cost 一步到位。
Iterator trait: 一切迭代的根源
next() 是唯一必须实现的方法。所有其他方法——map, filter, take, fold, collect——都是基于 next() 的默认实现。这意味着只要实现 next(),你的类型自动获得整个迭代器生态。
Lazy Evaluation: 迭代器不做任何事,直到被"驱动"
let v: =
.filter // 不发生 — 只是构建链
.map // 不发生
.take // 不发生
.collect; // 现在! 所有 adaptors 被"驱动"
// → [0, 4, 8]
这段代码在 collect() 之前不会处理任何一个元素。当 collect() 调用 next() 时,它从 take 请求,take 从 map 请求,map 从 filter 请求,filter 从 0..10 请求——形成一条"拉"链。这与 eager evaluation(如 Python list comprehension)有根本区别。
关键 Adaptors
| adaptor | 作用 | 何时触发 |
|---|---|---|
map | 转换每个元素 | lazy |
filter | 保留满足条件的 | lazy |
take(n) | 取前 n 个后停止 | lazy |
skip(n) | 跳过前 n 个 | lazy |
enumerate | 附加索引 (index, item) | lazy |
chain | 拼接两个迭代器 | lazy |
flat_map | 每个元素展开为迭代器 | lazy |
fold | 累积 (reduce) | eager (消耗迭代器) |
collect | 收集为集合 | eager |
三种闭包 Trait: FnOnce → FnMut → Fn
这三个 trait 形成一条约束链:
FnOnce: 只能调用一次 — consume 捕获的值 (ownership 转移)
FnMut: `&mut self` — 可以修改捕获的值, 可以多次调用
Fn: `&self` — 只读捕获, 可以多次调用, 最通用
- 所有闭包默认实现
FnOnce - 如果闭包不 consume 捕获的值 → 也实现
FnMut - 如果闭包不修改捕获的值 → 也实现
Fn
let s = Stringfrom;
let f = ; // s 被 move 进闭包 — 这是一个 FnOnce
// f() 只能调用一次 — 调用后 s 被 consume, f 不能再被调用
let mut v = vec!;
let mut f = ; // 修改 v — FnMut (can call multiple times)
let x = 42;
let f = ; // 只读 — Fn (most general)
零成本迭代
release 模式下,迭代器链通常被编译器"融合"为单个循环——map, filter, collect 的连续调用被优化为等价的 for loop,没有额外分配,没有虚函数调用。这就是 Rust 的 zero-cost abstraction 在迭代器上的体现。
参考
- Rust Book: Chapter 13
- Rust Reference: Fn traits, Iterator
Keywords: Iterator, lazy evaluation, collect, Fn, FnMut, FnOnce, adaptor, zero-cost