组合器详解
Rust 标准库组合器速查
or() 和 and()
跟布尔关系的与/或很像,这两个方法会对两个表达式做逻辑组合,最终返回 Option / Result。
or(),表达式按照顺序求值,若任何一个表达式的结果是Some或Ok,则该值会立刻返回and(),若两个表达式的结果都是Some或Ok,则第二个表达式中的值被返回。若任何一个的结果是None或Err,则立刻返回。
Rust 组合器速查表
Option · Result · Iterator — 按使用频率排序,示例均可直接运行
场景标签: 链式调用 默认值 类型转换 条件判断 错误处理 收集聚合
Option<T>
| # | 组合器 | 签名简述 | 场景 |
|---|---|---|---|
| ① | .map() | Option<T> → Option<U> | 链式调用 |
| ② | .unwrap_or() | Option<T> → T | 默认值 |
| ③ | .and_then() | Option<T> → Option<U>(可返回 None) | 链式调用 |
| ④ | .unwrap_or_else() | 惰性求值默认值(闭包) | 默认值 |
| ⑤ | .ok_or() | Option<T> → Result<T, E> | 类型转换 |
| ⑥ | .filter() | 条件不满足时变为 None | 条件判断 |
| ⑦ | .or_else() | None 时返回另一个 Option | 默认值 |
| ⑧ | .is_some() / .is_none() | 返回 bool | 条件判断 |
| ⑨ | .as_ref() | 借用内部值,避免消耗所有权 | 类型转换 |
| ⑩ | .map_or() | map + unwrap_or 合一 | 默认值 / 链式调用 |
| ⑪ | .take() | 取出值,原位置置 None(需 &mut) | 类型转换 |
| ⑫ | .flatten() | Option<Option<T>> → Option<T> | 类型转换 |
示例
// ① .map() — 变换 Some 内的值,None 穿透
let n: Option<i32> = Some(3);
let s = n.map(|x| x * 2); // Some(6)
// ② .unwrap_or() — 提供默认值
let v: Option<&str> = None;
let s = v.unwrap_or("guest"); // "guest"
// ③ .and_then() — 链式操作,闭包可返回 None(flatMap)
let s = Some("42");
s.and_then(|x| x.parse::<i32>().ok()) // Some(42)
// ④ .unwrap_or_else() — 惰性求值,适合创建代价较大的默认值
let v: Option<Vec<i32>> = None;
v.unwrap_or_else(|| vec![1, 2]) // [1, 2]
// ⑤ .ok_or() — Option 转 Result,None 映射为指定错误
let x: Option<i32> = None;
x.ok_or("missing") // Err("missing")
// ⑥ .filter() — 条件不满足时变为 None
Some(4).filter(|&x| x % 2 == 0) // Some(4)
Some(3).filter(|&x| x % 2 == 0) // None
// ⑦ .or_else() — None 时执行备用逻辑
let a: Option<i32> = None;
a.or_else(|| Some(99)) // Some(99)
// ⑧ .is_some() / .is_none() — 不消耗所有权地检查
let x = Some(1);
if x.is_some() { /* 有值 */ }
// ⑨ .as_ref() — 借用内部值,避免 move
let s = Some(String::from("hi"));
s.as_ref().map(|x| x.len()) // Some(2),s 仍可用
// ⑩ .map_or() — map + unwrap_or 合一
Some(5).map_or(0, |x| x * 2) // 10
None::<i32>.map_or(0, |x| x * 2) // 0
// ⑪ .take() — 取出值,原位置置 None
let mut x = Some(42);
let y = x.take(); // y = Some(42),x = None
// ⑫ .flatten() — 展平嵌套 Option
Some(Some(3)).flatten() // Some(3)
Some(None::<i32>).flatten() // None
Result<T, E>
| # | 组合器 | 签名简述 | 场景 |
|---|---|---|---|
| ① | ? 运算符 | Err 时提前返回,自动传播 | 错误处理 |
| ② | .map() | 变换 Ok 值,Err 穿透 | 链式调用 |
| ③ | .map_err() | 变换 Err 值,统一错误类型 | 错误处理 / 类型转换 |
| ④ | .and_then() | 链式 Result 操作(flatMap) | 链式调用 / 错误处理 |
| ⑤ | .unwrap_or() | Err 时返回默认值 | 默认值 |
| ⑥ | .unwrap_or_else() | Err 时惰性求值默认值 | 默认值 |
| ⑦ | .ok() | Result<T,E> → Option<T>(丢弃错误) | 类型转换 |
| ⑧ | .or_else() | Err 时执行备用逻辑 | 错误处理 |
| ⑨ | .is_ok() / .is_err() | 不消耗所有权地检查状态 | 条件判断 |
| ⑩ | .inspect_err() | 调试打印,不消耗值(Rust 1.76+) | 错误处理 |
| ⑪ | collect::<Result<V,E>>() | 迭代器收集,遇到 Err 立即停止 | 收集聚合 / 错误处理 |
示例
// ① ? 运算符 — 最常用,Err 时自动 return
fn run() -> Result<(), Box<dyn std::error::Error>> {
let n: i32 = "5".parse()?; // 解析失败则提前返回 Err
println!("{n}");
Ok(())
}
// ② .map() — 变换 Ok 值
Ok(2_i32).map(|x| x * 3) // Ok(6)
Err::<i32, &str>("oops").map(|x| x * 3) // Err("oops")
// ③ .map_err() — 统一错误类型
"x".parse::<i32>()
.map_err(|e| format!("parse fail: {e}")) // Err("parse fail: ...")
// ④ .and_then() — 链式校验
"8".parse::<i32>()
.and_then(|n| if n > 0 { Ok(n) } else { Err("非正数".parse::<i32>().unwrap_err()) })
// ⑤ .unwrap_or() — Err 时返回默认值
"bad".parse::<i32>().unwrap_or(0) // 0
// ⑥ .unwrap_or_else() — 惰性默认值
"bad".parse::<i32>().unwrap_or_else(|_| -1) // -1
// ⑦ .ok() — 转为 Option,丢弃错误信息
"42".parse::<i32>().ok() // Some(42)
"x".parse::<i32>().ok() // None
// ⑧ .or_else() — 失败时执行备用逻辑
"x".parse::<i32>()
.or_else(|_| "0".parse::<i32>()) // Ok(0)
// ⑨ .is_ok() / .is_err()
let r = "5".parse::<i32>();
if r.is_ok() { /* 解析成功 */ }
// ⑩ .inspect_err() — 调试用,不消耗值(Rust 1.76+)
"x".parse::<i32>()
.inspect_err(|e| eprintln!("err: {e}"));
// ⑪ collect::<Result<Vec<_>, _>>() — 遇到第一个 Err 就停止
let v: Result<Vec<i32>, _> =
vec!["1", "2", "3"].iter().map(|s| s.parse()).collect();
// Ok([1, 2, 3])
let v: Result<Vec<i32>, _> =
vec!["1", "x", "3"].iter().map(|s| s.parse()).collect();
// Err(ParseIntError)
Iterator
| # | 组合器 | 签名简述 | 场景 |
|---|---|---|---|
| ① | .map() | 逐元素变换,惰性求值 | 链式调用 |
| ② | .filter() | 保留满足条件的元素 | 条件判断 |
| ③ | .collect() | 收集为 Vec / HashMap / String 等 | 收集聚合 |
| ④ | .fold() | 带初始值的聚合(最通用) | 收集聚合 |
| ⑤ | .flat_map() | map 后展平一层(map + flatten) | 链式调用 |
| ⑥ | .enumerate() | 附带下标 (index, value) | 链式调用 |
| ⑦ | .filter_map() | filter + map 合一,None 自动过滤 | 条件判断 / 链式调用 |
| ⑧ | .any() / .all() | 短路求值,返回 bool | 条件判断 |
| ⑨ | .take() / .skip() | 前 N 个 / 跳过前 N 个 | 链式调用 |
| ⑩ | .zip() | 两迭代器逐对打包 | 链式调用 |
| ⑪ | .chain() | 拼接两个迭代器 | 链式调用 |
| ⑫ | .find() / .position() | 找值 Option<&T> / 找下标 Option<usize> | 条件判断 |
| ⑬ | .sum() / .product() | 求和 / 求积(需类型标注) | 收集聚合 |
| ⑭ | .max() / .min() | 最大 / 最小值,返回 Option | 收集聚合 |
| ⑮ | .cloned() / .copied() | Iterator<&T> → Iterator<T>,消除引用 | 类型转换 |
示例
// ① .map() — 逐元素变换,惰性,需终止符驱动
vec![1, 2, 3].iter().map(|x| x * 2).collect::<Vec<_>>() // [2, 4, 6]
// ② .filter() — 保留满足条件的元素
vec![1, 2, 3, 4].iter().filter(|&&x| x > 2).collect::<Vec<_>>() // [3, 4]
// ③ .collect() — 收集为各种集合类型
(1..4).collect::<Vec<i32>>() // [1, 2, 3]
(1..4).collect::<std::collections::HashSet<_>>()
// ④ .fold() — 带初始值的通用聚合
vec![1, 2, 3].iter().fold(0, |acc, x| acc + x) // 6
vec![1, 2, 3].iter().fold(1, |acc, x| acc * x) // 6
// ⑤ .flat_map() — map 后展平一层
vec!["a b", "c d"].iter()
.flat_map(|s| s.split(' '))
.collect::<Vec<_>>() // ["a", "b", "c", "d"]
// ⑥ .enumerate() — 附带下标
for (i, v) in vec!["a", "b", "c"].iter().enumerate() {
println!("{i}: {v}"); // 0: a 1: b 2: c
}
// ⑦ .filter_map() — 过滤 + 变换,None 自动丢弃
vec!["1", "x", "3"].iter()
.filter_map(|s| s.parse::<i32>().ok())
.collect::<Vec<_>>() // [1, 3]
// ⑧ .any() / .all() — 短路求值
vec![1, 2, 3].iter().any(|&x| x > 2) // true
vec![2, 4, 6].iter().all(|&x| x % 2 == 0) // true
// ⑨ .take() / .skip()
(0..).take(3).collect::<Vec<_>>() // [0, 1, 2](无限迭代器截断)
(0..5).skip(3).collect::<Vec<_>>() // [3, 4]
// ⑩ .zip() — 两迭代器逐对打包,以较短者为准
let a = vec![1, 2];
let b = vec!["a", "b"];
a.iter().zip(b.iter()).collect::<Vec<_>>() // [(1,"a"), (2,"b")]
// ⑪ .chain() — 拼接两个迭代器
vec![1, 2].iter().chain(vec![3, 4].iter())
.collect::<Vec<_>>() // [1, 2, 3, 4]
// ⑫ .find() / .position()
vec![1, 2, 3].iter().find(|&&x| x > 1) // Some(&2)
vec![1, 2, 3].iter().position(|&x| x == 2) // Some(1)
// ⑬ .sum() / .product() — 需显式类型标注
let s: i32 = vec![1, 2, 3].iter().sum(); // 6
let p: i32 = vec![1, 2, 3].iter().product(); // 6
// ⑭ .max() / .min() — 空迭代器返回 None
vec![3, 1, 4, 1, 5].iter().max() // Some(5)
vec![3, 1, 4, 1, 5].iter().min() // Some(1)
// ⑮ .copied() / .cloned() — 消除迭代器中的引用层
vec![1, 2, 3].iter().copied().collect::<Vec<i32>>() // 适用 Copy 类型
vec!["a".to_string()].iter().cloned().collect::<Vec<String>>() // 适用 Clone 类型
常用组合模式
// 模式 1:解析 + 过滤 + 收集(filter_map 最简洁)
let nums: Vec<i32> = input.split(',')
.filter_map(|s| s.trim().parse().ok())
.collect();
// 模式 2:Option 链式处理
let display = user.get("name") // Option<&str>
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.unwrap_or("匿名");
// 模式 3:Result 链式校验
fn validate(s: &str) -> Result<i32, String> {
s.parse::<i32>()
.map_err(|e| format!("格式错误: {e}"))
.and_then(|n| if n > 0 { Ok(n) } else { Err("必须为正数".into()) })
}
// 模式 4:迭代器批量处理 Result(全成功才返回 Ok)
let results: Result<Vec<i32>, _> = raw_inputs.iter()
.map(|s| s.parse::<i32>())
.collect();
// 模式 5:enumerate + filter_map 找带下标的值
let found: Vec<(usize, i32)> = data.iter()
.enumerate()
.filter_map(|(i, &v)| if v > 10 { Some((i, v)) } else { None })
.collect();
迭代器是惰性的,
.map().filter()等不会立即执行,只有遇到.collect().fold().sum()等终止符时才真正运算。
Option 组合器完整指南
Option 是函数式编程中表示可选值的核心类型,它要么包含一个值(Some(T)),要么不包含值(None)。组合器(Combinator)是一系列链式调用的方法,让你无需显式的 if let/match 就能安全地处理可选值,避免空指针异常。
以下是 Rust 标准库中 Option<T> 的所有组合器,按功能分类并附带完整示例。
一、基础判断组合器
用于检查 Option 是否包含值,或值是否满足特定条件。
1. is_some()
- 功能:如果 Option 是
Some,返回true - 签名:
fn is_some(&self) -> bool
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert!(some_value.is_some());
assert!(!none_value.is_some());
2. is_none()
- 功能:如果 Option 是
None,返回true - 签名:
fn is_none(&self) -> bool
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert!(!some_value.is_none());
assert!(none_value.is_none());
3. is_some_and() (Rust 1.70+)
- 功能:如果 Option 是
Some且包含的值满足给定谓词,返回true - 签名:
fn is_some_and(&self, f: impl FnOnce(&T) -> bool) -> bool
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert!(some_value.is_some_and(|&x| x > 0));
assert!(!some_value.is_some_and(|&x| x < 0));
assert!(!none_value.is_some_and(|&x| x > 0));
二、值转换组合器
将 Option 中的值转换为另一种类型,或在值不存在时提供默认值。
1. map()
- 功能:如果是
Some,应用函数f到值上并返回新的Some;否则返回None - 签名:
fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.map(|x| x * 2), Some(84));
assert_eq!(none_value.map(|x| x * 2), None);
2. map_or()
- 功能:如果是
Some,应用函数f到值上;否则返回默认值default - 签名:
fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.map_or(0, |x| x * 2), 84);
assert_eq!(none_value.map_or(0, |x| x * 2), 0);
3. map_or_else()
- 功能:如果是
Some,应用函数f到值上;否则调用default函数获取默认值 - 签名:
fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.map_or_else(|| 0, |x| x * 2), 84);
assert_eq!(none_value.map_or_else(|| 0, |x| x * 2), 0);
4. and_then() (flat_map)
- 功能:如果是
Some,应用函数f到值上并返回结果(必须是 Option);否则返回None - 签名:
fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U>
// 链式处理多个可能失败的操作
fn divide(a: i32, b: i32) -> Option<i32> {
if b == 0 { None } else { Some(a / b) }
}
let result = Some(10).and_then(|x| divide(x, 2)).and_then(|x| divide(x, 5));
assert_eq!(result, Some(1));
let result = Some(10).and_then(|x| divide(x, 0)).and_then(|x| divide(x, 5));
assert_eq!(result, None);
三、组合多个 Option
将多个 Option 组合成一个新的 Option。
1. and()
- 功能:如果
self是Some,返回optb;否则返回None - 签名:
fn and<U>(self, optb: Option<U>) -> Option<U>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.and(Some("hello")), Some("hello"));
assert_eq!(none_value.and(Some("hello")), None);
assert_eq!(some_value.and(None), None);
2. or()
- 功能:如果
self是Some,返回self;否则返回optb - 签名:
fn or(self, optb: Option<T>) -> Option<T>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.or(Some(100)), Some(42));
assert_eq!(none_value.or(Some(100)), Some(100));
assert_eq!(none_value.or(none_value), None);
3. or_else()
- 功能:如果
self是Some,返回self;否则调用f函数获取备选 Option - 签名:
fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.or_else(|| Some(100)), Some(42));
assert_eq!(none_value.or_else(|| Some(100)), Some(100));
4. xor()
- 功能:如果
self和optb中恰好有一个是Some,返回那个Some;否则返回None - 签名:
fn xor(self, optb: Option<T>) -> Option<T>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.xor(none_value), Some(42));
assert_eq!(none_value.xor(some_value), Some(42));
assert_eq!(some_value.xor(some_value), None);
assert_eq!(none_value.xor(none_value), None);
5. zip()
- 功能:将两个 Option 组合成一个包含元组的 Option;如果有一个是
None,返回None - 签名:
fn zip<U>(self, other: Option<U>) -> Option<(T, U)>
let some1: Option<i32> = Some(42);
let some2: Option<&str> = Some("hello");
let none_value: Option<i32> = None;
assert_eq!(some1.zip(some2), Some((42, "hello")));
assert_eq!(some1.zip(none_value), None);
6. zip_with() (Rust 1.46+)
- 功能:将两个 Option 的值应用函数
f并返回结果;如果有一个是None,返回None - 签名:
fn zip_with<U, R, F: FnOnce(T, U) -> R>(self, other: Option<U>, f: F) -> Option<R>
let some1: Option<i32> = Some(42);
let some2: Option<i32> = Some(10);
let none_value: Option<i32> = None;
assert_eq!(some1.zip_with(some2, |a, b| a + b), Some(52));
assert_eq!(some1.zip_with(none_value, |a, b| a + b), None);
四、过滤与扁平化
1. filter()
- 功能:如果是
Some且值满足谓词f,返回self;否则返回None - 签名:
fn filter<P: FnOnce(&T) -> bool>(self, f: P) -> Option<T>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.filter(|&x| x > 0), Some(42));
assert_eq!(some_value.filter(|&x| x < 0), None);
assert_eq!(none_value.filter(|&x| x > 0), None);
2. flatten() (Rust 1.40+)
- 功能:将嵌套的 Option(
Option<Option<T>>)扁平化一层 - 签名:
fn flatten(self) -> Option<T>
let nested_some: Option<Option<i32>> = Some(Some(42));
let nested_none1: Option<Option<i32>> = Some(None);
let nested_none2: Option<Option<i32>> = None;
assert_eq!(nested_some.flatten(), Some(42));
assert_eq!(nested_none1.flatten(), None);
assert_eq!(nested_none2.flatten(), None);
五、值提取组合器
从 Option 中提取值,或在值不存在时处理错误。
1. unwrap()
- 功能:如果是
Some,返回包含的值;否则 panic - 签名:
fn unwrap(self) -> T
let some_value: Option<i32> = Some(42);
assert_eq!(some_value.unwrap(), 42);
// 以下代码会 panic
// let none_value: Option<i32> = None;
// none_value.unwrap();
2. unwrap_or()
- 功能:如果是
Some,返回包含的值;否则返回默认值default - 签名:
fn unwrap_or(self, default: T) -> T
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.unwrap_or(0), 42);
assert_eq!(none_value.unwrap_or(0), 0);
3. unwrap_or_else()
- 功能:如果是
Some,返回包含的值;否则调用f函数获取默认值 - 签名:
fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.unwrap_or_else(|| 0), 42);
assert_eq!(none_value.unwrap_or_else(|| 0), 0);
4. expect()
- 功能:如果是
Some,返回包含的值;否则 panic 并显示指定的错误信息 - 签名:
fn expect(self, msg: &str) -> T
let some_value: Option<i32> = Some(42);
assert_eq!(some_value.expect("值不存在"), 42);
// 以下代码会 panic 并显示 "值不存在"
// let none_value: Option<i32> = None;
// none_value.expect("值不存在");
5. ok_or()
- 功能:将 Option 转换为 Result;如果是
Some,返回Ok(value);否则返回Err(err) - 签名:
fn ok_or<E>(self, err: E) -> Result<T, E>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.ok_or("错误"), Ok(42));
assert_eq!(none_value.ok_or("错误"), Err("错误"));
6. ok_or_else()
- 功能:将 Option 转换为 Result;如果是
Some,返回Ok(value);否则调用err函数获取错误值 - 签名:
fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E>
let some_value: Option<i32> = Some(42);
let none_value: Option<i32> = None;
assert_eq!(some_value.ok_or_else(|| "错误"), Ok(42));
assert_eq!(none_value.ok_or_else(|| "错误"), Err("错误"));
六、引用与可变引用
将 Option 转换为对其内部值的引用或可变引用,避免所有权转移。
1. as_ref()
- 功能:将
&Option<T>转换为Option<&T> - 签名:
fn as_ref(&self) -> Option<&T>
let some_value: Option<i32> = Some(42);
let ref_value: Option<&i32> = some_value.as_ref();
assert_eq!(ref_value, Some(&42));
2. as_mut()
- 功能:将
&mut Option<T>转换为Option<&mut T> - 签名:
fn as_mut(&mut self) -> Option<&mut T>
let mut some_value: Option<i32> = Some(42);
if let Some(x) = some_value.as_mut() {
*x = 100;
}
assert_eq!(some_value, Some(100));
七、其他实用组合器
1. transpose() (Rust 1.33+)
- 功能:将
Option<Result<T, E>>转换为Result<Option<T>, E> - 签名:
fn transpose(self) -> Result<Option<T>, E>
let some_ok: Option<Result<i32, &str>> = Some(Ok(42));
let some_err: Option<Result<i32, &str>> = Some(Err("错误"));
let none_value: Option<Result<i32, &str>> = None;
assert_eq!(some_ok.transpose(), Ok(Some(42)));
assert_eq!(some_err.transpose(), Err("错误"));
assert_eq!(none_value.transpose(), Ok(None));
2. take()
- 功能:取出 Option 中的值,将原 Option 置为
None - 签名:
fn take(&mut self) -> Option<T>
let mut some_value: Option<i32> = Some(42);
let taken_value = some_value.take();
assert_eq!(taken_value, Some(42));
assert_eq!(some_value, None);
3. replace()
- 功能:用新值替换 Option 中的值,返回原来的值
- 签名:
fn replace(&mut self, value: T) -> Option<T>
let mut some_value: Option<i32> = Some(42);
let old_value = some_value.replace(100);
assert_eq!(old_value, Some(42));
assert_eq!(some_value, Some(100));
4. copied() (Rust 1.35+)
- 功能:将
Option<&T>转换为Option<T>(要求 T 实现 Copy trait) - 签名:
fn copied(self) -> Option<T>
let value = 42;
let ref_option: Option<&i32> = Some(&value);
let copied_option: Option<i32> = ref_option.copied();
assert_eq!(copied_option, Some(42));
5. cloned() (Rust 1.0+)
- 功能:将
Option<&T>转换为Option<T>(要求 T 实现 Clone trait) - 签名:
fn cloned(self) -> Option<T>
let value = String::from("hello");
let ref_option: Option<&String> = Some(&value);
let cloned_option: Option<String> = ref_option.cloned();
assert_eq!(cloned_option, Some(String::from("hello")));
八、组合器链式调用示例
Option 组合器的强大之处在于可以链式调用,优雅地处理复杂的可选值逻辑:
// 从用户输入中解析年龄,验证是否在合法范围内,然后计算出生年份
fn calculate_birth_year(input: Option<&str>) -> Option<i32> {
input
.and_then(|s| s.parse::<i32>().ok()) // 解析字符串为整数
.filter(|&age| age >= 0 && age <= 120) // 验证年龄范围
.map(|age| 2026 - age) // 计算出生年份
}
assert_eq!(calculate_birth_year(Some("25")), Some(2001));
assert_eq!(calculate_birth_year(Some("150")), None); // 年龄不合法
assert_eq!(calculate_birth_year(Some("abc")), None); // 解析失败
assert_eq!(calculate_birth_year(None), None); // 无输入
总结
Option 组合器让你以声明式的方式处理可选值,避免了繁琐的 if let/match 嵌套,使代码更简洁、更易读、更安全。在实际开发中,应优先使用组合器而非显式的空检查和 panic。
Result 组合器完整指南
Result<T, E> 是 Rust 中表示操作结果的核心类型,它要么包含成功值(Ok(T)),要么包含错误值(Err(E))。组合器(Combinator)让你无需显式的 match 就能安全地处理成功和错误两种情况,是 Rust 错误处理的基石。
以下是 Rust 标准库中 Result<T, E> 的所有组合器,按功能分类并附带完整示例(基于 Rust 1.77+ 最新版本)。
%% ? 运算符,Err 时提前返回,自动传播、错误处理 %%
一、基础判断组合器
用于检查 Result 是成功还是失败,或值是否满足特定条件。
1. is_ok()
- 功能:如果 Result 是
Ok,返回true - 签名:
fn is_ok(&self) -> bool
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert!(ok_value.is_ok());
assert!(!err_value.is_ok());
2. is_err()
- 功能:如果 Result 是
Err,返回true - 签名:
fn is_err(&self) -> bool
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert!(!ok_value.is_err());
assert!(err_value.is_err());
3. is_ok_and() (Rust 1.70+)
- 功能:如果 Result 是
Ok且成功值满足给定谓词,返回true - 签名:
fn is_ok_and(&self, f: impl FnOnce(&T) -> bool) -> bool
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert!(ok_value.is_ok_and(|&x| x > 0));
assert!(!ok_value.is_ok_and(|&x| x < 0));
assert!(!err_value.is_ok_and(|&x| x > 0));
4. is_err_and() (Rust 1.70+)
- 功能:如果 Result 是
Err且错误值满足给定谓词,返回true - 签名:
fn is_err_and(&self, f: impl FnOnce(&E) -> bool) -> bool
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("网络错误");
assert!(err_value.is_err_and(|e| e.contains("网络")));
assert!(!err_value.is_err_and(|e| e.contains("数据库")));
assert!(!ok_value.is_err_and(|e| e.contains("网络")));
二、值转换组合器
将 Result 中的成功值或错误值转换为另一种类型。
1. map()
- 功能:如果是
Ok,应用函数f到成功值上并返回新的Ok;否则返回原Err - 签名:
fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Result<U, E>
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.map(|x| x * 2), Ok(84));
assert_eq!(err_value.map(|x| x * 2), Err("出错了"));
2. map_err()
- 功能:如果是
Err,应用函数f到错误值上并返回新的Err;否则返回原Ok - 签名:
fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F>
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("原始错误");
assert_eq!(ok_value.map_err(|e| format!("错误:{}", e)), Ok(42));
assert_eq!(err_value.map_err(|e| format!("错误:{}", e)), Err("错误:原始错误"));
3. map_or()
- 功能:如果是
Ok,应用函数f到成功值上;否则返回默认值default - 签名:
fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.map_or(0, |x| x * 2), 84);
assert_eq!(err_value.map_or(0, |x| x * 2), 0);
4. map_or_else()
- 功能:如果是
Ok,应用函数f到成功值上;否则调用default函数获取默认值 - 签名:
fn map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.map_or_else(|_| 0, |x| x * 2), 84);
assert_eq!(err_value.map_or_else(|e| e.len() as i32, |x| x * 2), 4);
5. and_then() (flat_map)
- 功能:如果是
Ok,应用函数f到成功值上并返回结果(必须是 Result);否则返回原Err - 签名:
fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, f: F) -> Result<U, E>
// 链式处理多个可能失败的操作
fn divide(a: i32, b: i32) -> Result<i32, &'static str> {
if b == 0 { Err("除数不能为零") } else { Ok(a / b) }
}
let result = Ok(10).and_then(|x| divide(x, 2)).and_then(|x| divide(x, 5));
assert_eq!(result, Ok(1));
let result = Ok(10).and_then(|x| divide(x, 0)).and_then(|x| divide(x, 5));
assert_eq!(result, Err("除数不能为零"));
6. or_else()
- 功能:如果是
Err,应用函数f到错误值上并返回结果(必须是 Result);否则返回原Ok - 签名:
fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F>
// 错误恢复:如果数据库查询失败,尝试从缓存获取
fn query_db(id: i32) -> Result<String, &'static str> {
Err("数据库连接失败")
}
fn query_cache(id: i32) -> Result<String, &'static str> {
Ok(format!("缓存数据:{}", id))
}
let result = query_db(42).or_else(|_| query_cache(42));
assert_eq!(result, Ok("缓存数据:42"));
7. inspect() (Rust 1.76+)
- 功能:如果是
Ok,对成功值执行副作用操作(如日志),然后返回原 Result - 签名:
fn inspect<F: FnOnce(&T)>(self, f: F) -> Self
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
// 仅在成功时打印日志
ok_value.inspect(|x| println!("成功获取值:{}", x));
err_value.inspect(|x| println!("成功获取值:{}", x)); // 不会执行
8. inspect_err() (Rust 1.76+)
- 功能:如果是
Err,对错误值执行副作用操作(如日志),然后返回原 Result - 签名:
fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
// 仅在失败时打印日志
ok_value.inspect_err(|e| eprintln!("错误:{}", e)); // 不会执行
err_value.inspect_err(|e| eprintln!("错误:{}", e));
三、组合多个 Result
将多个 Result 组合成一个新的 Result。
1. and()
- 功能:如果
self是Ok,返回res;否则返回原Err - 签名:
fn and<U>(self, res: Result<U, E>) -> Result<U, E>
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.and(Ok("hello")), Ok("hello"));
assert_eq!(err_value.and(Ok("hello")), Err("出错了"));
assert_eq!(ok_value.and(Err("另一个错误")), Err("另一个错误"));
2. or()
- 功能:如果
self是Ok,返回self;否则返回res - 签名:
fn or<F>(self, res: Result<T, F>) -> Result<T, F>
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.or(Ok(100)), Ok(42));
assert_eq!(err_value.or(Ok(100)), Ok(100));
assert_eq!(err_value.or(Err("另一个错误")), Err("另一个错误"));
3. xor() (Rust 1.73+)
- 功能:如果
self和res中恰好有一个是Ok,返回那个Ok;否则返回Err - 签名:
fn xor(self, res: Result<T, E>) -> Result<T, E> where E: Default
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.xor(err_value), Ok(42));
assert_eq!(err_value.xor(ok_value), Ok(42));
assert_eq!(ok_value.xor(ok_value), Err("")); // E::default() 对于 &str 是 ""
assert_eq!(err_value.xor(err_value), Err(""));
四、与 Option 的转换
在 Result 和 Option 之间进行转换。
1. ok()
- 功能:将 Result 转换为 Option;如果是
Ok,返回Some(value);否则返回None - 签名:
fn ok(self) -> Option<T>
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.ok(), Some(42));
assert_eq!(err_value.ok(), None);
2. err()
- 功能:将 Result 转换为 Option;如果是
Err,返回Some(error);否则返回None - 签名:
fn err(self) -> Option<E>
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.err(), None);
assert_eq!(err_value.err(), Some("出错了"));
3. transpose() (Rust 1.33+)
- 功能:将
Result<Option<T>, E>转换为Option<Result<T, E>> - 签名:
fn transpose(self) -> Option<Result<T, E>>
let ok_some: Result<Option<i32>, &str> = Ok(Some(42));
let ok_none: Result<Option<i32>, &str> = Ok(None);
let err_value: Result<Option<i32>, &str> = Err("出错了");
assert_eq!(ok_some.transpose(), Some(Ok(42)));
assert_eq!(ok_none.transpose(), None);
assert_eq!(err_value.transpose(), Some(Err("出错了")));
五、扁平化与嵌套处理
1. flatten() (Rust 1.70+)
- 功能:将嵌套的 Result(
Result<Result<T, E>, E>)扁平化一层 - 签名:
fn flatten(self) -> Result<T, E>
let nested_ok: Result<Result<i32, &str>, &str> = Ok(Ok(42));
let nested_err1: Result<Result<i32, &str>, &str> = Ok(Err("内部错误"));
let nested_err2: Result<Result<i32, &str>, &str> = Err("外部错误");
assert_eq!(nested_ok.flatten(), Ok(42));
assert_eq!(nested_err1.flatten(), Err("内部错误"));
assert_eq!(nested_err2.flatten(), Err("外部错误"));
六、值提取组合器
从 Result 中提取值,或在失败时处理错误。
1. unwrap()
- 功能:如果是
Ok,返回成功值;否则 panic - 签名:
fn unwrap(self) -> T where E: Debug
let ok_value: Result<i32, &str> = Ok(42);
assert_eq!(ok_value.unwrap(), 42);
// 以下代码会 panic
// let err_value: Result<i32, &str> = Err("出错了");
// err_value.unwrap();
2. unwrap_err()
- 功能:如果是
Err,返回错误值;否则 panic - 签名:
fn unwrap_err(self) -> E where T: Debug
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(err_value.unwrap_err(), "出错了");
// 以下代码会 panic
// let ok_value: Result<i32, &str> = Ok(42);
// ok_value.unwrap_err();
3. unwrap_or()
- 功能:如果是
Ok,返回成功值;否则返回默认值default - 签名:
fn unwrap_or(self, default: T) -> T
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.unwrap_or(0), 42);
assert_eq!(err_value.unwrap_or(0), 0);
4. unwrap_or_else()
- 功能:如果是
Ok,返回成功值;否则调用f函数获取默认值 - 签名:
fn unwrap_or_else<F: FnOnce(E) -> T>(self, f: F) -> T
let ok_value: Result<i32, &str> = Ok(42);
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(ok_value.unwrap_or_else(|_| 0), 42);
assert_eq!(err_value.unwrap_or_else(|e| e.len() as i32), 4);
5. expect()
- 功能:如果是
Ok,返回成功值;否则 panic 并显示指定的错误信息 - 签名:
fn expect(self, msg: &str) -> T where E: Debug
let ok_value: Result<i32, &str> = Ok(42);
assert_eq!(ok_value.expect("操作失败"), 42);
// 以下代码会 panic 并显示 "操作失败:出错了"
// let err_value: Result<i32, &str> = Err("出错了");
// err_value.expect("操作失败");
6. expect_err()
- 功能:如果是
Err,返回错误值;否则 panic 并显示指定的错误信息 - 签名:
fn expect_err(self, msg: &str) -> E where T: Debug
let err_value: Result<i32, &str> = Err("出错了");
assert_eq!(err_value.expect_err("应该失败"), "出错了");
// 以下代码会 panic 并显示 "应该失败:42"
// let ok_value: Result<i32, &str> = Ok(42);
// ok_value.expect_err("应该失败");
7. into_ok() (Rust 1.77+)
- 功能:将 Result 转换为成功值 T;如果是 Err 则 panic
- 签名:
fn into_ok(self) -> T where E: Into<!>
// 适用于错误类型是 !(永不发生)的情况
let ok_value: Result<i32, !> = Ok(42);
assert_eq!(ok_value.into_ok(), 42);
8. into_err() (Rust 1.77+)
- 功能:将 Result 转换为错误值 E;如果是 Ok 则 panic
- 签名:
fn into_err(self) -> E where T: Into<!>
// 适用于成功类型是 !(永不发生)的情况
let err_value: Result<!, &str> = Err("出错了");
assert_eq!(err_value.into_err(), "出错了");
七、引用与可变引用
将 Result 转换为对其内部值的引用或可变引用,避免所有权转移。
1. as_ref()
- 功能:将
&Result<T, E>转换为Result<&T, &E> - 签名:
fn as_ref(&self) -> Result<&T, &E>
let ok_value: Result<i32, &str> = Ok(42);
let ref_value: Result<&i32, &&str> = ok_value.as_ref();
assert_eq!(ref_value, Ok(&42));
2. as_mut()
- 功能:将
&mut Result<T, E>转换为Result<&mut T, &mut E> - 签名:
fn as_mut(&mut self) -> Result<&mut T, &mut E>
let mut ok_value: Result<i32, &str> = Ok(42);
if let Ok(x) = ok_value.as_mut() {
*x = 100;
}
assert_eq!(ok_value, Ok(100));
八、其他实用组合器
1. take()
- 功能:取出 Result 中的值,将原 Result 置为
Err(E::default()) - 签名:
fn take(&mut self) -> Result<T, E> where E: Default
let mut ok_value: Result<i32, &str> = Ok(42);
let taken_value = ok_value.take();
assert_eq!(taken_value, Ok(42));
assert_eq!(ok_value, Err("")); // E::default() 对于 &str 是 ""
2. replace()
- 功能:用新值替换 Result 中的值,返回原来的值
- 签名:
fn replace(&mut self, value: T) -> Result<T, E>
let mut ok_value: Result<i32, &str> = Ok(42);
let old_value = ok_value.replace(100);
assert_eq!(old_value, Ok(42));
assert_eq!(ok_value, Ok(100));
3. copied() (Rust 1.59+)
- 功能:将
Result<&T, &E>转换为Result<T, E>(要求 T 和 E 实现 Copy trait) - 签名:
fn copied<'a, T: Copy, E: Copy>(self) -> Result<T, E>
let value = 42;
let ref_result: Result<&i32, &&str> = Ok(&value);
let copied_result: Result<i32, &str> = ref_result.copied();
assert_eq!(copied_result, Ok(42));
4. cloned() (Rust 1.59+)
- 功能:将
Result<&T, &E>转换为Result<T, E>(要求 T 和 E 实现 Clone trait) - 签名:
fn cloned<'a, T: Clone, E: Clone>(self) -> Result<T, E>
let value = String::from("hello");
let ref_result: Result<&String, &&str> = Ok(&value);
let cloned_result: Result<String, &str> = ref_result.cloned();
assert_eq!(cloned_result, Ok(String::from("hello")));
九、组合器链式调用示例
Result 组合器的强大之处在于可以链式调用,优雅地处理复杂的错误处理逻辑:
// 从用户输入中解析数字,验证范围,然后计算平方根
fn calculate_sqrt(input: &str) -> Result<f64, String> {
input
.parse::<f64>()
.map_err(|e| format!("解析失败:{}", e))
.and_then(|n| {
if n >= 0.0 {
Ok(n)
} else {
Err(format!("负数没有实数平方根:{}", n))
}
})
.map(|n| n.sqrt())
.inspect(|sqrt| println!("计算结果:{}", sqrt))
}
assert!(calculate_sqrt("25").is_ok_and(|&x| (x - 5.0).abs() < 1e-9));
assert_eq!(calculate_sqrt("-4"), Err("负数没有实数平方根:-4".to_string()));
assert!(calculate_sqrt("abc").is_err_and(|e| e.starts_with("解析失败")));
总结
Result 组合器是 Rust 错误处理的核心,让你以声明式的方式处理成功和错误两种情况,避免了繁琐的 match 嵌套和显式的错误检查。在实际开发中,应优先使用组合器而非 unwrap()/expect(),除非你能绝对保证操作不会失败。
Rust Iterator 组合器完整指南
迭代器(Iterator)是 Rust 中处理集合的核心抽象,它允许你以声明式的方式对元素序列进行操作。组合器是迭代器上的一系列方法,它们消费一个迭代器并返回一个新的迭代器,支持无限链式调用,是 Rust 函数式编程风格的基石。
以下是 Rust 标准库中 Iterator trait 的所有组合器(截至 Rust 1.77+),按功能分类并附带完整可运行示例。
一、基础转换组合器
将迭代器中的每个元素转换为另一种形式。
1. map()
- 功能:对每个元素应用函数
f,返回包含转换后元素的新迭代器 - 签名:
fn map<B, F>(self, f: F) -> Map<Self, F> where F: FnMut(Self::Item) -> B
let numbers = vec![1, 2, 3, 4];
let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
assert_eq!(doubled, vec![2, 4, 6, 8]);
2. map_while() (Rust 1.57+)
- 功能:对元素应用函数
f,直到返回None为止,返回包含成功值的迭代器 - 签名:
fn map_while<B, F>(self, f: F) -> MapWhile<Self, F> where F: FnMut(Self::Item) -> Option<B>
let numbers = vec![1, 2, 3, -1, 4, 5];
let positive: Vec<i32> = numbers.into_iter()
.map_while(|x| if x > 0 { Some(x * 2) } else { None })
.collect();
assert_eq!(positive, vec![2, 4, 6]); // 遇到 -1 停止
3. flat_map()
- 功能:对每个元素应用函数
f(返回迭代器),然后将所有结果迭代器扁平化 - 签名:
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> where F: FnMut(Self::Item) -> U, U: IntoIterator
let words = vec!["hello", "world"];
let chars: Vec<char> = words.iter().flat_map(|s| s.chars()).collect();
assert_eq!(chars, vec!['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']);
4. enumerate()
- 功能:为每个元素添加索引,返回
(索引, 元素)对的迭代器 - 签名:
fn enumerate(self) -> Enumerate<Self>
let fruits = vec!["apple", "banana", "cherry"];
let indexed: Vec<(usize, &str)> = fruits.iter().enumerate().collect();
assert_eq!(indexed, vec![(0, "apple"), (1, "banana"), (2, "cherry")]);
二、过滤与筛选组合器
从迭代器中选择满足特定条件的元素。
1. filter()
- 功能:保留满足谓词
f的元素 - 签名:
fn filter<P>(self, predicate: P) -> Filter<Self, P> where P: FnMut(&Self::Item) -> bool
let numbers = vec![1, 2, 3, 4, 5, 6];
let even: Vec<i32> = numbers.into_iter().filter(|x| x % 2 == 0).collect();
assert_eq!(even, vec![2, 4, 6]);
2. filter_map()
- 功能:对每个元素应用函数
f,保留返回Some的值 - 签名:
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where F: FnMut(Self::Item) -> Option<B>
let strings = vec!["1", "2", "three", "4", "five"];
let numbers: Vec<i32> = strings.into_iter()
.filter_map(|s| s.parse::<i32>().ok())
.collect();
assert_eq!(numbers, vec![1, 2, 4]);
3. take()
- 功能:取前
n个元素,然后停止 - 签名:
fn take(self, n: usize) -> Take<Self>
let numbers = vec![1, 2, 3, 4, 5];
let first_three: Vec<i32> = numbers.into_iter().take(3).collect();
assert_eq!(first_three, vec![1, 2, 3]);
4. take_while()
- 功能:取元素直到谓词
f返回false为止 - 签名:
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where P: FnMut(&Self::Item) -> bool
let numbers = vec![1, 2, 3, -1, 4, 5];
let positive: Vec<i32> = numbers.into_iter()
.take_while(|&x| x > 0)
.collect();
assert_eq!(positive, vec![1, 2, 3]);
5. skip()
- 功能:跳过前
n个元素 - 签名:
fn skip(self, n: usize) -> Skip<Self>
let numbers = vec![1, 2, 3, 4, 5];
let after_three: Vec<i32> = numbers.into_iter().skip(3).collect();
assert_eq!(after_three, vec![4, 5]);
6. skip_while()
- 功能:跳过元素直到谓词
f返回false为止 - 签名:
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where P: FnMut(&Self::Item) -> bool
let numbers = vec![-1, -2, 0, 1, 2];
let positive: Vec<i32> = numbers.into_iter()
.skip_while(|&x| x < 0)
.collect();
assert_eq!(positive, vec![0, 1, 2]);
7. step_by() (Rust 1.28+)
- 功能:从第一个元素开始,每隔
step个元素取一个 - 签名:
fn step_by(self, step: usize) -> StepBy<Self>
let numbers = vec![0, 1, 2, 3, 4, 5, 6];
let even_indices: Vec<i32> = numbers.into_iter().step_by(2).collect();
assert_eq!(even_indices, vec![0, 2, 4, 6]);
三、扁平化与嵌套处理
处理嵌套的迭代器结构。
1. flatten() (Rust 1.29+)
- 功能:将嵌套的迭代器(
Iterator<Item=IntoIterator>)扁平化一层 - 签名:
fn flatten(self) -> Flatten<Self> where Self::Item: IntoIterator
let nested = vec![vec![1, 2], vec![3, 4], vec![5, 6]];
let flattened: Vec<i32> = nested.into_iter().flatten().collect();
assert_eq!(flattened, vec![1, 2, 3, 4, 5, 6]);
2. flat_map()
- 功能:先
map再flatten,是最常用的扁平化组合器 - 示例见"基础转换组合器"部分
四、组合多个迭代器
将多个迭代器合并或交错在一起。
1. chain()
- 功能:将两个迭代器连接起来,先迭代完第一个,再迭代第二个
- 签名:
fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> where U: IntoIterator<Item = Self::Item>
let a = vec![1, 2, 3];
let b = vec![4, 5, 6];
let combined: Vec<i32> = a.into_iter().chain(b).collect();
assert_eq!(combined, vec![1, 2, 3, 4, 5, 6]);
2. zip()
- 功能:将两个迭代器的元素配对,返回元组的迭代器,直到其中一个迭代器结束
- 签名:
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> where U: IntoIterator
let numbers = vec![1, 2, 3];
let letters = vec!['a', 'b', 'c'];
let zipped: Vec<(i32, char)> = numbers.into_iter().zip(letters).collect();
assert_eq!(zipped, vec![(1, 'a'), (2, 'b'), (3, 'c')]);
3. interleave() (Rust 1.73+)
- 功能:交错两个迭代器的元素,先取第一个迭代器的一个元素,再取第二个的一个,依此类推
- 签名:
fn interleave<U>(self, other: U) -> Interleave<Self, U::IntoIter> where U: IntoIterator<Item = Self::Item>
let a = vec![1, 3, 5];
let b = vec![2, 4, 6];
let interleaved: Vec<i32> = a.into_iter().interleave(b).collect();
assert_eq!(interleaved, vec![1, 2, 3, 4, 5, 6]);
4. intersperse() (Rust 1.71+)
- 功能:在迭代器的每个元素之间插入一个分隔符
- 签名:
fn intersperse(self, separator: Self::Item) -> Intersperse<Self> where Self::Item: Clone
let words = vec!["hello", "world", "rust"];
let with_spaces: String = words.into_iter().intersperse(" ").collect();
assert_eq!(with_spaces, "hello world rust");
5. intersperse_with() (Rust 1.71+)
- 功能:在迭代器的每个元素之间插入由函数生成的分隔符
- 签名:
fn intersperse_with<F>(self, separator: F) -> IntersperseWith<Self, F> where F: FnMut() -> Self::Item
let numbers = vec![1, 2, 3];
let with_commas: String = numbers
.into_iter()
.map(|x| x.to_string())
.intersperse_with(|| ", ".to_string())
.collect();
assert_eq!(with_commas, "1, 2, 3");
五、排序与去重
对迭代器中的元素进行排序或去除重复项。
1. sorted() (Rust 1.77+)
- 功能:对迭代器中的元素进行排序(要求元素实现
Ordtrait) - 签名:
fn sorted(self) -> impl Iterator<Item = Self::Item> where Self::Item: Ord
let numbers = vec![3, 1, 4, 1, 5, 9, 2, 6];
let sorted: Vec<i32> = numbers.into_iter().sorted().collect();
assert_eq!(sorted, vec![1, 1, 2, 3, 4, 5, 6, 9]);
2. sorted_by()
- 功能:使用自定义比较函数对元素进行排序
- 签名:
fn sorted_by<F>(self, compare: F) -> impl Iterator<Item = Self::Item> where F: FnMut(&Self::Item, &Self::Item) -> Ordering
let mut numbers = vec![3, 1, 4, 1, 5, 9, 2, 6];
let sorted_desc: Vec<i32> = numbers.into_iter()
.sorted_by(|a, b| b.cmp(a))
.collect();
assert_eq!(sorted_desc, vec![9, 6, 5, 4, 3, 2, 1, 1]);
3. sorted_by_key()
- 功能:根据键提取函数生成的键对元素进行排序
- 签名:
fn sorted_by_key<K, F>(self, f: F) -> impl Iterator<Item = Self::Item> where K: Ord, F: FnMut(&Self::Item) -> K
let people = vec![("Alice", 30), ("Bob", 25), ("Charlie", 35)];
let sorted_by_age: Vec<(&str, i32)> = people.into_iter()
.sorted_by_key(|&(_, age)| age)
.collect();
assert_eq!(sorted_by_age, vec![("Bob", 25), ("Alice", 30), ("Charlie", 35)]);
4. dedup() (Rust 1.77+)
- 功能:去除连续的重复元素(要求元素实现
PartialEqtrait) - 签名:
fn dedup(self) -> impl Iterator<Item = Self::Item> where Self::Item: PartialEq
let numbers = vec![1, 1, 2, 2, 3, 3, 3, 4];
let deduped: Vec<i32> = numbers.into_iter().dedup().collect();
assert_eq!(deduped, vec![1, 2, 3, 4]);
5. dedup_by() (Rust 1.77+)
- 功能:使用自定义相等性判断去除连续的重复元素
- 签名:
fn dedup_by<F>(self, same_bucket: F) -> impl Iterator<Item = Self::Item> where F: FnMut(&Self::Item, &Self::Item) -> bool
let numbers = vec![1, 3, 5, 2, 4, 6];
// 去除奇偶性相同的连续元素
let deduped: Vec<i32> = numbers.into_iter()
.dedup_by(|a, b| a % 2 == b % 2)
.collect();
assert_eq!(deduped, vec![1, 2]);
6. dedup_by_key() (Rust 1.77+)
- 功能:根据键提取函数生成的键去除连续的重复元素
- 签名:
fn dedup_by_key<K, F>(self, key: F) -> impl Iterator<Item = Self::Item> where K: PartialEq, F: FnMut(&Self::Item) -> K
let people = vec![("Alice", 30), ("Alice", 35), ("Bob", 25), ("Bob", 30)];
// 去除名字相同的连续元素
let deduped: Vec<(&str, i32)> = people.into_iter()
.dedup_by_key(|&(name, _)| name)
.collect();
assert_eq!(deduped, vec![("Alice", 30), ("Bob", 25)]);
六、折叠与聚合
将迭代器中的所有元素聚合为单个值。
1. fold()
- 功能:从初始值开始,对每个元素应用累加函数,返回最终结果
- 签名:
fn fold<B, F>(self, init: B, f: F) -> B where F: FnMut(B, Self::Item) -> B
let numbers = vec![1, 2, 3, 4];
let sum: i32 = numbers.iter().fold(0, |acc, x| acc + x);
assert_eq!(sum, 10);
2. reduce()
- 功能:与
fold类似,但使用第一个元素作为初始值,返回Option(空迭代器返回None) - 签名:
fn reduce<F>(self, f: F) -> Option<Self::Item> where F: FnMut(Self::Item, Self::Item) -> Self::Item
let numbers = vec![1, 2, 3, 4];
let sum: Option<i32> = numbers.into_iter().reduce(|acc, x| acc + x);
assert_eq!(sum, Some(10));
let empty: Vec<i32> = vec![];
let sum_empty: Option<i32> = empty.into_iter().reduce(|acc, x| acc + x);
assert_eq!(sum_empty, None);
3. scan()
- 功能:与
fold类似,但保留中间结果,返回包含所有中间状态的迭代器 - 签名:
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> where F: FnMut(&mut St, Self::Item) -> Option<B>
let numbers = vec![1, 2, 3, 4];
let partial_sums: Vec<i32> = numbers.into_iter()
.scan(0, |acc, x| {
*acc += x;
Some(*acc)
})
.collect();
assert_eq!(partial_sums, vec![1, 3, 6, 10]);
4. sum()
- 功能:计算迭代器中所有元素的和
- 签名:
fn sum<S>(self) -> S where S: Sum<Self::Item>
let numbers = vec![1, 2, 3, 4];
let sum: i32 = numbers.iter().sum();
assert_eq!(sum, 10);
5. product()
- 功能:计算迭代器中所有元素的乘积
- 签名:
fn product<P>(self) -> P where P: Product<Self::Item>
let numbers = vec![1, 2, 3, 4];
let product: i32 = numbers.iter().product();
assert_eq!(product, 24);
6. count()
- 功能:计算迭代器中元素的个数
- 签名:
fn count(self) -> usize
let numbers = vec![1, 2, 3, 4];
assert_eq!(numbers.iter().count(), 4);
7. max()
- 功能:返回迭代器中的最大值(要求元素实现
Ordtrait) - 签名:
fn max(self) -> Option<Self::Item> where Self::Item: Ord
let numbers = vec![3, 1, 4, 1, 5, 9, 2, 6];
assert_eq!(numbers.into_iter().max(), Some(9));
8. min()
- 功能:返回迭代器中的最小值(要求元素实现
Ordtrait) - 签名:
fn min(self) -> Option<Self::Item> where Self::Item: Ord
let numbers = vec![3, 1, 4, 1, 5, 9, 2, 6];
assert_eq!(numbers.into_iter().min(), Some(1));
9. max_by_key()
- 功能:根据键提取函数生成的键返回最大值
- 签名:
fn max_by_key<K, F>(self, f: F) -> Option<Self::Item> where K: Ord, F: FnMut(&Self::Item) -> K
let people = vec![("Alice", 30), ("Bob", 25), ("Charlie", 35)];
let oldest = people.into_iter().max_by_key(|&(_, age)| age);
assert_eq!(oldest, Some(("Charlie", 35)));
10. min_by_key()
- 功能:根据键提取函数生成的键返回最小值
- 签名:
fn min_by_key<K, F>(self, f: F) -> Option<Self::Item> where K: Ord, F: FnMut(&Self::Item) -> K
let people = vec![("Alice", 30), ("Bob", 25), ("Charlie", 35)];
let youngest = people.into_iter().min_by_key(|&(_, age)| age);
assert_eq!(youngest, Some(("Bob", 25)));
七、条件与短路操作
检查迭代器中的元素是否满足特定条件,支持短路求值。
1. all()
- 功能:如果所有元素都满足谓词
f,返回true;否则返回false(短路) - 签名:
fn all<F>(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool
let numbers = vec![2, 4, 6, 8];
assert!(numbers.iter().all(|&x| x % 2 == 0));
assert!(!numbers.iter().all(|&x| x > 5));
2. any()
- 功能:如果有任何一个元素满足谓词
f,返回true;否则返回false(短路) - 签名:
fn any<F>(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool
let numbers = vec![1, 3, 5, 7, 8];
assert!(numbers.iter().any(|&x| x % 2 == 0));
assert!(!numbers.iter().any(|&x| x > 10));
3. find()
- 功能:返回第一个满足谓词
f的元素(短路) - 签名:
fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool
let numbers = vec![1, 2, 3, 4, 5];
assert_eq!(numbers.iter().find(|&&x| x > 3), Some(&4));
assert_eq!(numbers.iter().find(|&&x| x > 10), None);
4. find_map()
- 功能:对元素应用函数
f,返回第一个Some值(短路) - 签名:
fn find_map<B, F>(&mut self, f: F) -> Option<B> where F: FnMut(Self::Item) -> Option<B>
let strings = vec!["one", "2", "three", "4", "five"];
let first_number = strings.iter().find_map(|s| s.parse::<i32>().ok());
assert_eq!(first_number, Some(2));
5. position()
- 功能:返回第一个满足谓词
f的元素的索引(短路) - 签名:
fn position<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool
let numbers = vec![1, 2, 3, 4, 5];
assert_eq!(numbers.iter().position(|&x| x > 3), Some(3));
assert_eq!(numbers.iter().position(|&x| x > 10), None);
6. rposition()
- 功能:从后往前查找,返回最后一个满足谓词
f的元素的索引(短路) - 签名:
fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: ExactSizeIterator + DoubleEndedIterator
let numbers = vec![1, 2, 3, 4, 5, 4, 3, 2, 1];
assert_eq!(numbers.iter().rposition(|&x| x > 3), Some(5));
八、迭代器控制
改变迭代器的行为或顺序。
1. rev()
- 功能:反转迭代器的顺序(要求迭代器实现
DoubleEndedIteratortrait) - 签名:
fn rev(self) -> Rev<Self> where Self: DoubleEndedIterator
let numbers = vec![1, 2, 3, 4];
let reversed: Vec<i32> = numbers.into_iter().rev().collect();
assert_eq!(reversed, vec![4, 3, 2, 1]);
2. cycle()
- 功能:无限重复迭代器(要求迭代器实现
Clonetrait) - 签名:
fn cycle(self) -> Cycle<Self> where Self: Clone
let numbers = vec![1, 2, 3];
let mut cycle = numbers.into_iter().cycle();
assert_eq!(cycle.next(), Some(1));
assert_eq!(cycle.next(), Some(2));
assert_eq!(cycle.next(), Some(3));
assert_eq!(cycle.next(), Some(1)); // 重复
3. peekable()
- 功能:创建一个可以查看下一个元素而不消费它的迭代器
- 签名:
fn peekable(self) -> Peekable<Self>
let mut peekable = vec![1, 2, 3].into_iter().peekable();
assert_eq!(peekable.peek(), Some(&1)); // 查看但不消费
assert_eq!(peekable.next(), Some(1)); // 消费
assert_eq!(peekable.peek(), Some(&2));
4. fuse()
- 功能:创建一个迭代器,一旦返回
None,就永远返回None - 签名:
fn fuse(self) -> Fuse<Self>
// 有些迭代器在返回 None 后可能继续返回 Some,fuse 可以防止这种情况
let mut iter = vec![1, 2, 3].into_iter().fuse();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None); // 永远返回 None
九、副作用与调试
在迭代过程中执行副作用操作,如打印日志。
1. inspect()
- 功能:对每个元素执行副作用操作,然后返回原元素
- 签名:
fn inspect<F>(self, f: F) -> Inspect<Self, F> where F: FnMut(&Self::Item)
let numbers = vec![1, 2, 3, 4];
let sum: i32 = numbers.iter()
.inspect(|x| println!("处理元素:{}", x))
.map(|x| x * 2)
.inspect(|x| println!("加倍后:{}", x))
.sum();
assert_eq!(sum, 20);
十、转换为其他集合类型
将迭代器转换为各种集合类型。
1. collect()
- 功能:将迭代器转换为实现了
FromIteratortrait 的集合类型 - 签名:
fn collect<B: FromIterator<Self::Item>>(self) -> B
let numbers = vec![1, 2, 3, 4];
let vec: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
let set: std::collections::HashSet<i32> = numbers.into_iter().collect();
let string: String = vec!['h', 'e', 'l', 'l', 'o'].into_iter().collect();
2. partition()
- 功能:根据谓词将迭代器分为两个集合
- 签名:
fn partition<B, F>(self, f: F) -> (B, B) where B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool
let numbers = vec![1, 2, 3, 4, 5, 6];
let (even, odd): (Vec<i32>, Vec<i32>) = numbers.into_iter()
.partition(|&x| x % 2 == 0);
assert_eq!(even, vec![2, 4, 6]);
assert_eq!(odd, vec![1, 3, 5]);
3. unzip()
- 功能:将元组的迭代器拆分为两个独立的集合
- 签名:
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Iterator<Item = (A, B)>
let pairs = vec![(1, 'a'), (2, 'b'), (3, 'c')];
let (numbers, letters): (Vec<i32>, Vec<char>) = pairs.into_iter().unzip();
assert_eq!(numbers, vec![1, 2, 3]);
assert_eq!(letters, vec!['a', 'b', 'c']);
十一、综合示例:组合器链式调用
迭代器组合器的真正威力在于可以链式调用,优雅地解决复杂的数据处理问题:
// 计算所有长度大于3的单词中,每个单词的字母出现次数
fn count_letters(words: &[&str]) -> std::collections::HashMap<char, usize> {
words
.iter()
.filter(|&&word| word.len() > 3) // 过滤长度大于3的单词
.flat_map(|&word| word.chars()) // 拆分为字符
.map(|c| c.to_ascii_lowercase()) // 转换为小写
.fold(std::collections::HashMap::new(), |mut acc, c| {
*acc.entry(c).or_insert(0) += 1;
acc
})
}
let words = vec!["hello", "world", "rust", "is", "awesome"];
let counts = count_letters(&words);
assert_eq!(counts[&'h'], 1);
assert_eq!(counts[&'e'], 2);
assert_eq!(counts[&'l'], 3);
assert_eq!(counts[&'o'], 2);
总结
Rust 的迭代器组合器提供了一套强大且表达力极强的工具,让你以声明式的方式处理数据。它们不仅代码简洁易读,而且经过了高度优化,性能通常优于手动循环。
在实际开发中,应优先使用迭代器组合器而非手动循环,这是 Rust 编程的最佳实践之一。
Rust Future 组合器完整指南
Future 是 Rust 异步编程的核心抽象,代表一个尚未完成的异步操作。组合器(Combinator)是一系列链式调用的方法,让你无需显式的 poll 就能组合、转换和控制异步操作,是 Rust 异步编程的重要工具。
重要说明:Rust 标准库的 Future trait 仅定义了核心的 poll 方法,绝大多数实用组合器都在 futures crate(特别是 futures-util)中提供。本文基于 futures 0.3.30+ 和 tokio 1.37+ 版本,涵盖所有标准组合器。
注:实际开发中推荐使用 tokio/async-std 提供的更丰富的 Future 组合器
首先,在 Cargo.toml 中添加必要依赖:
[dependencies]
futures = "0.3.30"
tokio = { version = "1.37", features = ["full"] }
导入核心扩展 trait:
use futures::future::{FutureExt, TryFutureExt};
use tokio;
一、基础转换组合器
将 Future 的输出值或错误值转换为另一种类型。
1. map()
- 功能:如果 Future 成功完成,应用函数到输出值上,返回新的 Future
- 签名:
fn map<U, F>(self, f: F) -> Map<Self, F> where F: FnOnce(Self::Output) -> U
#[tokio::main]
async fn main() {
let future = async { 42 };
let mapped = future.map(|x| x * 2);
assert_eq!(mapped.await, 84);
}
2. map_err()
- 功能:如果 Future 返回错误,应用函数转换错误类型
- 签名:
fn map_err<E, F>(self, f: F) -> MapErr<Self, F> where F: FnOnce(Self::Error) -> E - 适用:仅用于输出为
Result<T, E>的 Future(实现了TryFuturetrait)
#[tokio::main]
async fn main() {
let future: Result<i32, &str> = Err("原始错误");
let mapped_err = future.map_err(|e| format!("错误:{}", e));
assert_eq!(mapped_err.await, Err("错误:原始错误".to_string()));
}
3. then()
- 功能:无论 Future 成功还是失败,都应用函数到结果上,返回新的 Future
- 签名:
fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F> where F: FnOnce(Self::Output) -> Fut, Fut: Future
#[tokio::main]
async fn main() {
let success = async { Ok::<i32, &str>(42) };
let failure = async { Err::<i32, &str>("出错了") };
let then_success = success.then(|res| async move {
match res {
Ok(x) => x * 2,
Err(_) => 0,
}
});
assert_eq!(then_success.await, 84);
let then_failure = failure.then(|res| async move {
match res {
Ok(x) => x * 2,
Err(_) => 0,
}
});
assert_eq!(then_failure.await, 0);
}
4. or_else()
- 功能:如果 Future 返回错误,应用函数进行错误恢复,返回新的 Future
- 签名:
fn or_else<Fut, F>(self, f: F) -> OrElse<Self, Fut, F> where F: FnOnce(Self::Error) -> Fut, Fut: TryFuture<Ok = Self::Ok>
#[tokio::main]
async fn main() {
// 模拟数据库查询失败,尝试从缓存获取
async fn query_db() -> Result<String, &'static str> {
Err("数据库连接失败")
}
async fn query_cache() -> Result<String, &'static str> {
Ok("缓存数据".to_string())
}
let result = query_db().or_else(|_| query_cache()).await;
assert_eq!(result, Ok("缓存数据".to_string()));
}
5. into_future()
- 功能:将任意值转换为已经完成的 Future
- 签名:
fn into_future(self) -> Ready<Self>
#[tokio::main]
async fn main() {
let value = 42;
let future = value.into_future();
assert_eq!(future.await, 42);
}
二、组合多个 Future
将多个 Future 组合成一个,控制它们的执行顺序和完成方式。
1. join! 宏
- 功能:并行运行多个 Future,等待所有完成,返回包含所有结果的元组
- 限制:最多支持 12 个 Future,更多请使用
join_all
#[tokio::main]
async fn main() {
let fut1 = async { 1 };
let fut2 = async { 2 };
let fut3 = async { 3 };
let (res1, res2, res3) = tokio::join!(fut1, fut2, fut3);
assert_eq!((res1, res2, res3), (1, 2, 3));
}
2. join_all()
- 功能:并行运行迭代器中的所有 Future,等待所有完成,返回结果 Vec
- 签名:
fn join_all<I>(iter: I) -> JoinAll<I::Item> where I: IntoIterator, I::Item: Future
use futures::future::join_all;
#[tokio::main]
async fn main() {
let futures = vec![
async { 1 },
async { 2 },
async { 3 },
];
let results = join_all(futures).await;
assert_eq!(results, vec![1, 2, 3]);
}
3. try_join! 宏
- 功能:并行运行多个
TryFuture,只要有一个失败就立即返回错误,否则返回成功值元组
#[tokio::main]
async fn main() {
let fut1 = async { Ok::<i32, &str>(1) };
let fut2 = async { Ok::<i32, &str>(2) };
let fut3 = async { Err::<i32, &str>("出错了") };
let result = tokio::try_join!(fut1, fut2, fut3);
assert_eq!(result, Err("出错了"));
}
4. try_join_all()
- 功能:并行运行迭代器中的所有
TryFuture,只要有一个失败就立即返回错误 - 签名:
fn try_join_all<I>(iter: I) -> TryJoinAll<I::Item> where I: IntoIterator, I::Item: TryFuture
use futures::future::try_join_all;
#[tokio::main]
async fn main() {
let futures = vec![
async { Ok::<i32, &str>(1) },
async { Ok::<i32, &str>(2) },
async { Ok::<i32, &str>(3) },
];
let results = try_join_all(futures).await;
assert_eq!(results, Ok(vec![1, 2, 3]));
}
5. select! 宏
- 功能:并行运行多个 Future,等待第一个完成的 Future,返回它的结果
- 特性:会自动取消未完成的 Future(支持取消的类型)
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let slow = sleep(Duration::from_millis(100)).map(|_| "慢操作");
let fast = sleep(Duration::from_millis(50)).map(|_| "快操作");
tokio::select! {
res = slow => assert_eq!(res, "慢操作"),
res = fast => assert_eq!(res, "快操作"), // 这个会先完成
}
}
6. select_all()
- 功能:并行运行迭代器中的所有 Future,返回第一个完成的结果和剩余的 Future
- 签名:
fn select_all<I>(iter: I) -> SelectAll<I::Item> where I: IntoIterator, I::Item: Future + Unpin
use futures::future::select_all;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let futures = vec![
sleep(Duration::from_millis(100)).map(|_| 1),
sleep(Duration::from_millis(50)).map(|_| 2),
sleep(Duration::from_millis(150)).map(|_| 3),
];
let (result, index, remaining) = select_all(futures).await;
assert_eq!(result, 2);
assert_eq!(index, 1);
assert_eq!(remaining.len(), 2);
}
7. race()
- 功能:与
select!类似,但不返回未完成的 Future,直接返回第一个完成的结果 - 签名:
fn race<Fut1, Fut2>(a: Fut1, b: Fut2) -> Race<Fut1, Fut2> where Fut1: Future, Fut2: Future<Output = Fut1::Output>
use futures::future::race;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let slow = sleep(Duration::from_millis(100)).map(|_| "慢操作");
let fast = sleep(Duration::from_millis(50)).map(|_| "快操作");
let result = race(slow, fast).await;
assert_eq!(result, "快操作");
}
8. race_ok! 宏
- 功能:并行运行多个
TryFuture,等待第一个成功完成的 Future;如果所有都失败,返回最后一个错误
use futures::future::race_ok;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let fut1 = async { Err::<&str, &str>("错误1") };
let fut2 = sleep(Duration::from_millis(50)).map(|_| Ok::<&str, &str>("成功"));
let fut3 = async { Err::<&str, &str>("错误2") };
let result = race_ok!(fut1, fut2, fut3).await;
assert_eq!(result, Ok("成功"));
}
9. zip()
- 功能:将两个 Future 组合成一个,等待两个都完成,返回结果元组
- 签名:
fn zip<Fut>(self, other: Fut) -> Zip<Self, Fut> where Fut: Future
#[tokio::main]
async fn main() {
let fut1 = async { 1 };
let fut2 = async { 2 };
let (res1, res2) = fut1.zip(fut2).await;
assert_eq!((res1, res2), (1, 2));
}
三、错误处理组合器
专门用于处理返回 Result 的 Future(TryFuture)。
1. unwrap()
- 功能:如果 Future 成功,返回成功值;否则 panic
- 签名:
fn unwrap(self) -> Unwrap<Self> where Self::Error: Debug
#[tokio::main]
async fn main() {
let success = async { Ok::<i32, &str>(42) };
assert_eq!(success.unwrap().await, 42);
// 以下代码会 panic
// let failure = async { Err::<i32, &str>("出错了") };
// failure.unwrap().await;
}
2. unwrap_err()
- 功能:如果 Future 失败,返回错误值;否则 panic
- 签名:
fn unwrap_err(self) -> UnwrapErr<Self> where Self::Ok: Debug
#[tokio::main]
async fn main() {
let failure = async { Err::<i32, &str>("出错了") };
assert_eq!(failure.unwrap_err().await, "出错了");
// 以下代码会 panic
// let success = async { Ok::<i32, &str>(42) };
// success.unwrap_err().await;
}
3. unwrap_or()
- 功能:如果 Future 成功,返回成功值;否则返回默认值
- 签名:
fn unwrap_or(self, default: Self::Ok) -> UnwrapOr<Self>
#[tokio::main]
async fn main() {
let success = async { Ok::<i32, &str>(42) };
let failure = async { Err::<i32, &str>("出错了") };
assert_eq!(success.unwrap_or(0).await, 42);
assert_eq!(failure.unwrap_or(0).await, 0);
}
4. unwrap_or_else()
- 功能:如果 Future 成功,返回成功值;否则调用函数获取默认值
- 签名:
fn unwrap_or_else<F>(self, f: F) -> UnwrapOrElse<Self, F> where F: FnOnce(Self::Error) -> Self::Ok
#[tokio::main]
async fn main() {
let failure = async { Err::<i32, &str>("出错了") };
let result = failure.unwrap_or_else(|e| e.len() as i32).await;
assert_eq!(result, 4); // "出错了" 长度是 4
}
5. expect()
- 功能:如果 Future 成功,返回成功值;否则 panic 并显示指定错误信息
- 签名:
fn expect(self, msg: &str) -> Expect<Self> where Self::Error: Debug
#[tokio::main]
async fn main() {
let success = async { Ok::<i32, &str>(42) };
assert_eq!(success.expect("操作失败").await, 42);
// 以下代码会 panic 并显示 "操作失败:出错了"
// let failure = async { Err::<i32, &str>("出错了") };
// failure.expect("操作失败").await;
}
6. ok()
- 功能:将
TryFuture转换为Future<Output=Option<T>>,成功返回Some(value),失败返回None - 签名:
fn ok(self) -> Ok<Self>
#[tokio::main]
async fn main() {
let success = async { Ok::<i32, &str>(42) };
let failure = async { Err::<i32, &str>("出错了") };
assert_eq!(success.ok().await, Some(42));
assert_eq!(failure.ok().await, None);
}
7. flatten()
- 功能:将嵌套的 Future(
Future<Output=Future<U>>)扁平化一层 - 签名:
fn flatten(self) -> Flatten<Self> where Self::Output: Future
#[tokio::main]
async fn main() {
let nested_future = async { async { 42 } };
let flattened = nested_future.flatten();
assert_eq!(flattened.await, 42);
}
8. transpose()
- 功能:将
Future<Output=Result<Option<T>, E>>转换为Future<Output=Option<Result<T, E>>> - 签名:
fn transpose(self) -> Transpose<Self> where Self::Output: Transpose
#[tokio::main]
async fn main() {
let ok_some: Result<Option<i32>, &str> = Ok(Some(42));
let ok_none: Result<Option<i32>, &str> = Ok(None);
let err: Result<Option<i32>, &str> = Err("出错了");
assert_eq!(ok_some.transpose().await, Some(Ok(42)));
assert_eq!(ok_none.transpose().await, None);
assert_eq!(err.transpose().await, Some(Err("出错了")));
}
四、控制流与实用组合器
改变 Future 的行为或提供实用功能。
1. fuse()
- 功能:创建一个 Future,一旦完成就永远返回
Poll::Ready(()),防止重复 poll 导致 panic - 签名:
fn fuse(self) -> Fuse<Self>
use futures::task::{noop_waker, Context, Poll};
use std::pin::Pin;
#[tokio::main]
async fn main() {
let mut future = async { 42 }.fuse();
assert_eq!(Pin::new(&mut future).await, 42);
// 再次 poll 不会 panic
let waker = noop_waker();
let mut cx = Context::from_waker(&waker);
assert_eq!(Pin::new(&mut future).poll(&mut cx), Poll::Ready(()));
}
2. inspect()
- 功能:对 Future 的成功结果执行副作用操作(如日志),然后返回原结果
- 签名:
fn inspect<F>(self, f: F) -> Inspect<Self, F> where F: FnOnce(&Self::Output)
#[tokio::main]
async fn main() {
let future = async { 42 }
.inspect(|x| println!("成功获取值:{}", x));
assert_eq!(future.await, 42);
}
3. inspect_err()
- 功能:对 Future 的错误结果执行副作用操作(如日志),然后返回原结果
- 签名:
fn inspect_err<F>(self, f: F) -> InspectErr<Self, F> where F: FnOnce(&Self::Error)
#[tokio::main]
async fn main() {
let future: Result<i32, &str> = Err("出错了")
.inspect_err(|e| eprintln!("错误:{}", e));
assert_eq!(future.await, Err("出错了"));
}
4. shared()
- 功能:创建一个可以克隆的 Future,多个克隆可以等待同一个 Future 的结果
- 签名:
fn shared(self) -> Shared<Self> where Self::Output: Clone - 用途:让多个任务共享同一个异步操作的结果,避免重复执行
use tokio::spawn;
#[tokio::main]
async fn main() {
let shared_future = async { 42 }.shared();
let fut1 = shared_future.clone();
let fut2 = shared_future.clone();
let handle1 = spawn(async move { fut1.await });
let handle2 = spawn(async move { fut2.await });
assert_eq!(handle1.await.unwrap(), 42);
assert_eq!(handle2.await.unwrap(), 42);
}
5. boxed()
- 功能:将 Future 装箱为
Pin<Box<dyn Future<Output = T> + Send>>,用于动态分发 - 签名:
fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>> where Self: Send + 'a
use std::future::Future;
fn create_future(flag: bool) -> Pin<Box<dyn Future<Output = i32> + Send>> {
if flag {
async { 42 }.boxed()
} else {
async { 100 }.boxed()
}
}
#[tokio::main]
async fn main() {
assert_eq!(create_future(true).await, 42);
assert_eq!(create_future(false).await, 100);
}
6. boxed_local()
- 功能:与
boxed()类似,但不要求Send,用于单线程运行时 - 签名:
fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>> where Self: 'a
use std::future::Future;
fn create_local_future(flag: bool) -> Pin<Box<dyn Future<Output = i32>>> {
if flag {
async { 42 }.boxed_local()
} else {
async { 100 }.boxed_local()
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
assert_eq!(create_local_future(true).await, 42);
assert_eq!(create_local_future(false).await, 100);
}
五、常用工具 Future
这些不是组合器,但经常与组合器一起使用,用于创建特定类型的 Future。
1. ready()
- 功能:创建一个已经完成的 Future,返回指定的值
- 签名:
fn ready<T>(value: T) -> Ready<T>
use futures::future::ready;
#[tokio::main]
async fn main() {
let future = ready(42);
assert_eq!(future.await, 42);
}
2. pending()
- 功能:创建一个永远不会完成的 Future
- 签名:
fn pending<T>() -> Pending<T>
use futures::future::{pending, race};
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let fut1 = pending::<i32>();
let fut2 = sleep(Duration::from_millis(50)).map(|_| 42);
let result = race(fut1, fut2).await;
assert_eq!(result, 42);
}
3. lazy()
- 功能:创建一个延迟执行的 Future,只有在第一次 poll 时才调用函数
- 签名:
fn lazy<F, R>(f: F) -> Lazy<F> where F: FnOnce() -> R, R: Future
use futures::future::lazy;
#[tokio::main]
async fn main() {
let future = lazy(|| async {
println!("Future 开始执行");
42
});
println!("Future 还没执行");
assert_eq!(future.await, 42); // 这里才会执行
}
六、超时与延迟(Tokio 提供)
这些组合器在 tokio 中提供,用于控制 Future 的执行时间。
1. timeout()
- 功能:给 Future 设置超时时间,如果在指定时间内没有完成,返回超时错误
- 签名:
fn timeout<F>(duration: Duration, future: F) -> Timeout<F> where F: Future
use tokio::time::{timeout, Duration};
#[tokio::main]
async fn main() {
let long_future = tokio::time::sleep(Duration::from_millis(200));
let result = timeout(Duration::from_millis(100), long_future).await;
assert!(result.is_err()); // 超时
}
2. sleep()
- 功能:创建一个延迟指定时间后完成的 Future
- 签名:
fn sleep(duration: Duration) -> Sleep
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let start = std::time::Instant::now();
sleep(Duration::from_millis(100)).await;
assert!(start.elapsed() >= Duration::from_millis(100));
}
七、综合示例:组合器链式调用
Future 组合器的强大之处在于可以链式调用,优雅地处理复杂的异步逻辑:
use tokio;
use tokio::time::{timeout, Duration};
// 模拟异步 API 调用
async fn fetch_data(id: i32) -> Result<String, &'static str> {
if id < 0 {
Err("无效的 ID")
} else {
Ok(format!("数据:{}", id))
}
}
#[tokio::main]
async fn main() {
let result = fetch_data(42)
.map_ok(|data| format!("处理后的{}", data)) // 转换成功值
.map_err(|e| format!("API 错误:{}", e)) // 转换错误值
.inspect(|res| println!("API 结果:{:?}", res)) // 打印结果
.timeout(Duration::from_millis(100)) // 设置超时
.await;
match result {
Ok(Ok(data)) => println!("成功:{}", data),
Ok(Err(e)) => eprintln!("错误:{}", e),
Err(_) => eprintln!("请求超时"),
}
}
总结
Future 组合器是 Rust 异步编程的重要工具,它们让你以声明式的方式组合和控制异步操作,避免了回调地狱。虽然现在 async/await 语法已经非常普及,但组合器在动态组合 Future、链式处理结果或错误时仍然非常有用。