Rust 学习笔记 18:闭包与迭代器 (Closures & Iterators)
“Functional programming is like backwards coding, everything is immutable and stateless… wait, Rust allows mutability?”
Rust 不仅仅是系统编程语言,它还拥有强大的函数式编程特性。其中最核心的两个就是:闭包和迭代器。
1. 闭包 (Closures)
闭包就是可以捕获其环境的匿名函数。
在 Go 中,我们经常写 func() { variableInOuterScope = 1 }。Rust 的闭包语法有点像 Ruby 的管道符 | |。
1let x = 4;
2let equal_to_x = |z| z == x; // 捕获了 x
3let y = 4;
4assert!(equal_to_x(y));
类型推断: 闭包不需要像函数那样强制标注参数和返回值类型,编译器会自动推断。
捕获方式: 闭包可以通过三种方式捕获环境,对应三个 Trait:
FnOnce:获取捕获变量的所有权(Move)。闭包只能被调用一次。FnMut:获取可变借用。可以修改环境。Fn:获取不可变借用。
2. 迭代器 (Iterators)
迭代器模式允许你对一个序列进行遍历。
在 Rust 中,迭代器是惰性 (Lazy) 的。如果你不调用 collect() 或 sum() 等消耗方法,迭代器本身什么都不做。
1let v1 = vec![1, 2, 3];
2let v1_iter = v1.iter(); // 此时还没开始遍历
3
4for val in v1_iter { // 这里才开始消耗
5 println!("Got: {}", val);
6}
Iterator Adaptors (适配器): 你可以链式调用多个方法来处理数据,这非常像 Java Stream API 或 JS 数组方法。
1let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
map 是一个适配器,它生成一个新的迭代器。collect 是一个消费者,它触发真正的计算。
3. 性能:零成本抽象
你可能会担心:用了这么多高阶函数和抽象,性能会不会很差?
完全不会。
Rust 的迭代器和闭包经过了极度优化。编译器会通过单态化和激进的内联,将这些高阶代码编译成和手写 for 循环(甚至汇编)一样高效的机器码。
事实上,在 Rust 中,迭代器往往比手动写的循环更快,因为它消除了边界检查 (Bounds Check)。
4. 小结
第十八篇笔记。
- 闭包 是能捕获环境的函数。
- 迭代器 提供了声明式处理序列的能力。
- 它们结合在一起,赋予了 Rust 强大的表达力,同时保持了底层的运行效率。
下一篇,我们将探讨 Rust 最独特的概念之一 —— 智能指针 (Smart Pointers)。如果你学过 C++,你会感到似曾相识;如果你只学过 Go/Java,这将为你打开新世界的大门。
练习题:
- 尝试使用迭代器及
filter,map方法,求出 1 到 100 之间所有能被 3 整除的数的平方和。 - 实现一个自定义迭代器(为你的结构体实现
IteratorTrait)。
思考题:
Go 语言的闭包捕获变量时,默认是引用捕获。Rust 提供了 move 关键字强制转移所有权 (move || ...)。这种显式控制所有权的机制在并发编程中有什么优势?
本文代码示例:
关注公众号:极客老墨
更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。
