跳到主要内容

集合

所有集合通用规则

  • iter():只读,返回不可变引用,原集合不受影响
  • iter_mut():可修改,返回可变引用,原集合不受影响
  • into_iter():转移所有权,返回元素本身,原集合被消耗
  • map/filter 仅能用于迭代器,不能直接用于集合本身
  • 惰性求值、零成本抽象 完全一致
方法返回迭代器元素类型所有权原集合适用场景
iter()Iter<'a, T>&T不可变引用可用只读遍历元素
iter_mut()IterMut<'a, T>&mut T可变引用可用修改集合元素(极少用)
into_iter()IntoIter<T>T所有权转移销毁拿走所有元素所有权

问题:

1、为啥 Option & Result 不需要iter,可以直接进行组合器调用?

**Vec/HashSet/HashMap 是「多元素集合」,自身没有实现组合器,必须用 iter() 生成迭代器才能调用 map/filter

Option/Result 是「0~1 个元素的值包装器」,它们**自己直接实现了 map/and_then 等组合器 **,和迭代器 Iterator 没有任何关系 **,所以根本不需要 iter()

集合类型(Vec/HashSet/BTreeMap)

  • 身份多元素容器(存放 N 个值,N ≥ 0)
  • 特性:本身不实现 Iterator,也没有自带 map/filter 方法
  • 必须:调用 iter()/into_iter() 生成一个迭代器,再用迭代器的组合器

Option / Result

  • 身份单子 (Monad) / 值包装器最多存 1 个值
    • Option<T>:要么有值 Some(T),要么无值 None
    • Result<T, E>:要么成功 Ok(T),要么失败 Err(E)
  • 特性自己实现了专属的 map/and_then/filter 方法
  • 无需:任何迭代器,直接调用组合器

源码实锤:组合器到底来自哪里?

Option 直接自带 map,Rust 标准库中 Optionmap 方法源码

// Option 自己的 impl 块,直接实现 map!
impl<T> Option<T> {
pub fn map<F, U>(self, f: F) -> Option<U>
where
F: FnOnce(T) -> U,
{
match self {
Some(x) => Some(f(x)), // 有值就处理
None => None, // 无值直接返回
}
}
}

Option::map自身方法,处理内部唯一的值

集合的 map 来自迭代器(必须先 iter ())

Vec 自身没有 map 方法mapIterator trait 提供的:

// Vec 本身没有 map!
// 你调用的 map 来自这里:
impl<I: Iterator> Iterator for I {
fn map<B, F>(self, f: F) -> Map<Self, F> { ... }
}

语义对比:同样叫 map,行为天差地别

调用方式来源处理对象行为逻辑
vec.iter().map()迭代器 Iterator多个元素遍历所有元素,逐个处理
option.map()Option 自身0/1 个元素只处理内部那个值,无值则跳过
result.map()Result 自身1 个成功值 / 错误只处理成功值,错误直接透传
// 1. 集合:必须 iter(),处理多个元素
let v = vec![1,2,3];
let v2 = v.iter().map(|x| x*2).collect::<Vec<_>>(); // [2,4,6]

// 2. Option:直接 map,处理单个值
let some_num = Some(5);
let opt2 = some_num.map(|x| x*2); // Some(10)

let none_num: Option<i32> = None;
let opt3 = none_num.map(|x| x*2); // None(直接跳过)

// 3. Result:直接 map,处理成功值
let ok_val: Result<i32, &str> = Ok(10);
let res2 = ok_val.map(|x| x*2); // Ok(20)

let err_val: Result<i32, &str> = Err("错误");
let res3 = err_val.map(|x| x*2); // Err("错误")(不处理)