闭包和迭代器是Rust函数式编程的核心。闭包是可以捕获环境的匿名函数,迭代器提供了惰性求值的元素序列。二者结合,让你写出简洁、高效、安全的链式数据处理代码。
学习目标:掌握闭包语法与捕获、Fn/FnMut/FnOnce特征、迭代器适配器与消费者、自定义迭代器
fn main() {
// 基本语法
let add = |a, b| a + b;
println!("3 + 5 = {}", add(3, 5));
// 类型推断:闭包通常不需要标注类型
let multiply = |x: i32, y: i32| -> i32 { x * y };
println!("4 * 6 = {}", multiply(4, 6));
// 多行闭包
let complex = |x: i32| {
let doubled = x * 2;
let squared = doubled * doubled;
squared
};
println!("复杂计算: {}", complex(3));
// 捕获环境变量
let factor = 3;
let scale = |x| x * factor; // 捕获factor
println!("缩放: {}", scale(10)); // 30
let greeting = String::from("Hello");
let say = || println!("{}", greeting); // 不可变借用greeting
say();
// greeting.push_str("!"); // ❌ say已借用greeting
// 捕获可变引用
let mut count = 0;
let mut increment = || {
count += 1;
count
};
println!("count = {}", increment());
println!("count = {}", increment());
println!("最终count = {}", count);
// move闭包:获取所有权
let name = String::from("Rust");
let owned = move || println!("拥有: {}", name);
// println!("{}", name); // ❌ name已被move
owned();
}
✅ 验证通过
| 特征 | 捕获方式 | 可调用次数 | 示例 |
|---|---|---|---|
| FnOnce | 获取所有权 | 一次 | 消耗捕获变量 |
| FnMut | 可变借用 | 多次(需mut) | 修改捕获变量 |
| Fn | 不可变借用 | 多次 | 只读捕获变量 |
// FnOnce —— 只能调用一次
fn apply_once(f: F) where F: FnOnce() {
f();
// f(); // ❌ 不能再调用
}
// FnMut —— 可多次调用,需要mut
fn apply_twice(mut f: F) where F: FnMut() {
f();
f();
}
// Fn —— 可多次调用,不可变
fn apply_many(f: F, n: usize) where F: Fn() {
for _ in 0..n {
f();
}
}
fn main() {
let mut x = 0;
// FnOnce: 消耗捕获的变量
let s = String::from("hello");
let consume = move || {
let _taken = s; // 获取所有权
println!("消耗了s");
};
apply_once(consume);
// FnMut: 修改捕获的变量
let mut counter = 0;
let mut increment = || { counter += 1; println!("counter={}", counter); };
apply_twice(increment);
// Fn: 只读
let msg = "你好";
let greet = || println!("{}", msg);
apply_many(greet, 3);
}
✅ 验证通过
fn main() {
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// map —— 转换每个元素
let squares: Vec = v.iter().map(|x| x * x).collect();
println!("平方: {:?}", squares);
// filter —— 过滤
let evens: Vec<&i32> = v.iter().filter(|x| *x % 2 == 0).collect();
println!("偶数: {:?}", evens);
// 链式调用!
let result: Vec = v.iter()
.filter(|x| *x % 2 == 0) // 偶数
.map(|x| x * 3) // 乘3
.take(3) // 取前3个
.collect();
println!("链式: {:?}", result);
// enumerate —— 带索引
for (i, v) in v.iter().enumerate().take(5) {
println!("[{}] = {}", i, v);
}
// zip —— 合并两个迭代器
let names = vec!["Alice", "Bob", "Charlie"];
let scores = vec![95, 87, 92];
let pairs: Vec<(&str, i32)> = names.iter().zip(scores.iter()).map(|(n, s)| (*n, *s)).collect();
println!("配对: {:?}", pairs);
// flat_map —— 展平
let words = vec!["hello world", "rust lang"];
let all_words: Vec<&str> = words.iter()
.flat_map(|s| s.split_whitespace())
.collect();
println!("展平: {:?}", all_words);
// inspect —— 查看中间值(调试用)
let sum: i32 = v.iter()
.inspect(|x| println!(" 检查: {}", x))
.take(3)
.sum();
println!("前3个和: {}", sum);
}
✅ 验证通过
fn main() {
let v = vec![1, 2, 3, 4, 5];
// collect —— 收集为集合
let v2: Vec = v.iter().cloned().collect();
// sum / product
println!("和: {}", v.iter().sum::());
println!("积: {}", v.iter().product::());
// min / max
println!("最小: {:?}", v.iter().min());
println!("最大: {:?}", v.iter().max());
// find / position
println!("找到>3: {:?}", v.iter().find(|&&x| x > 3));
println!("位置>3: {:?}", v.iter().position(|&x| x > 3));
// any / all
println!("有偶数: {}", v.iter().any(|&x| x % 2 == 0));
println!("全正数: {}", v.iter().all(|&x| x > 0));
// fold / reduce
let sum = v.iter().fold(0, |acc, &x| acc + x);
println!("fold求和: {}", sum);
let product = v.iter().cloned().reduce(|acc, x| acc * x);
println!("reduce求积: {:?}", product);
// for_each
v.iter().for_each(|x| print!("{} ", x));
println!();
// count
let even_count = v.iter().filter(|&&x| x % 2 == 0).count();
println!("偶数个数: {}", even_count);
}
✅ 验证通过
struct Fibonacci {
curr: u64,
next: u64,
}
impl Fibonacci {
fn new() -> Self {
Fibonacci { curr: 0, next: 1 }
}
}
impl Iterator for Fibonacci {
type Item = u64;
fn next(&mut self) -> Option {
let current = self.curr;
self.curr = self.next;
self.next = current + self.next;
Some(current)
}
}
struct RangeStep {
start: i32,
end: i32,
step: i32,
}
impl RangeStep {
fn new(start: i32, end: i32, step: i32) -> Self {
RangeStep { start, end, step }
}
}
impl Iterator for RangeStep {
type Item = i32;
fn next(&mut self) -> Option {
if self.start < self.end {
let val = self.start;
self.start += self.step;
Some(val)
} else {
None
}
}
}
fn main() {
// 斐波那契数列前10项
let fib: Vec = Fibonacci::new().take(10).collect();
println!("斐波那契: {:?}", fib);
// 前10个偶数斐波那契数
let even_fib: Vec = Fibonacci::new()
.filter(|&x| x % 2 == 0)
.take(5)
.collect();
println!("偶数斐波那契: {:?}", even_fib);
// 自定义步进范围
let stepped: Vec = RangeStep::new(0, 20, 3).collect();
println!("步进3: {:?}", stepped);
}
✅ 验证通过
use std::collections::HashMap;
#[derive(Debug, Clone)]
struct Student {
name: String,
scores: Vec,
}
impl Student {
fn new(name: &str, scores: Vec) -> Self {
Student { name: name.to_string(), scores }
}
fn average(&self) -> f64 {
if self.scores.is_empty() { return 0.0; }
self.scores.iter().sum::() / self.scores.len() as f64
}
fn highest(&self) -> Option {
self.scores.iter().cloned().fold(f64::NAN, f64::max).into()
}
}
fn main() {
let students = vec![
Student::new("Alice", vec![95.0, 88.0, 92.0, 90.0]),
Student::new("Bob", vec![78.0, 82.0, 75.0, 80.0]),
Student::new("Charlie", vec![99.0, 95.0, 98.0, 97.0]),
Student::new("Diana", vec![85.0, 90.0, 88.0, 92.0]),
Student::new("Eve", vec![72.0, 68.0, 75.0, 70.0]),
];
// 全班平均分
let class_avg = students.iter()
.map(|s| s.average())
.sum::() / students.len() as f64;
println!("📊 全班平均: {:.1}", class_avg);
// 排名(按平均分降序)
let mut ranked: Vec<_> = students.iter()
.map(|s| (s.name.clone(), s.average()))
.collect();
ranked.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
println!("\n🏆 排名:");
for (i, (name, avg)) in ranked.iter().enumerate() {
println!(" {}. {} ({:.1})", i + 1, name, avg);
}
// 优秀学生(平均>90)
let excellent: Vec<_> = students.iter()
.filter(|s| s.average() > 90.0)
.map(|s| s.name.clone())
.collect();
println!("\n🌟 优秀学生: {:?}", excellent);
// 各科统计
println!("\n📈 各科统计:");
let subject_count = students[0].scores.len();
for i in 0..subject_count {
let (avg, max, min) = students.iter()
.fold((0.0, f64::MIN, f64::MAX), |(sum, mx, mn), s| {
(sum + s.scores[i], mx.max(s.scores[i]), mn.min(s.scores[i]))
});
println!(" 科目{}: 均分={:.1} 最高={:.0} 最低={:.0}",
i + 1, avg / students.len() as f64, max, min);
}
}
✅ 验证通过
编写函数make_multiplier(factor: i32) -> impl Fn(i32) -> i32,返回一个乘法器闭包。
用迭代器实现:读取字符串列表→过滤长度>3→转大写→去重→排序→收集。
实现Primes迭代器,生成无限素数序列。使用take(20)测试。
🔒 下一课解锁:并发编程 —— 线程与通道
fn main() {
let data: Vec = (1..=1_000_000).collect();
// 命令式循环
let mut sum1 = 0i64;
for &x in &data {
if x % 2 == 0 { sum1 += x as i64 * x as i64; }
}
// 迭代器链(零成本抽象——编译后与上面相同)
let sum2: i64 = data.iter()
.filter(|&&x| x % 2 == 0)
.map(|&x| (x as i64) * (x as i64))
.sum();
assert_eq!(sum1, sum2);
println!("结果一致: {}", sum1);
println!("迭代器是零成本抽象——编译后与手写循环性能相同");
// 惰性求值
let iter = (1..).filter(|x| x % 2 == 0).map(|x| x * x);
let first_5: Vec = iter.take(5).collect();
println!("前5个偶数平方: {:?}", first_5);
// 无限迭代器 + take
let primes: Vec = {
let mut primes = vec![];
let mut n = 2u64;
while primes.len() < 10 {
if !primes.iter().any(|&p| n % p == 0) {
primes.push(n);
}
n += 1;
}
primes
};
println!("前10个素数: {:?}", primes);
}
✅ 验证通过