为何Rust的collect方法在两个相似函数中表现不同?
Rustlings iterators3练习:为什么两个collect调用返回不同结果?
在rustlings的iterators3练习里,有两个结构几乎一样的函数,调用collect后返回的结果却完全不同:
// 输出: Ok([1, 11, 1426, 3]) fn result_with_list() -> Result<Vec<i32>, DivisionError> { let numbers = vec![27, 297, 38502, 81]; let division_results = numbers.into_iter().map(|n| divide(n, 27)); let x: Result<Vec<i32>, DivisionError> = division_results.collect(); println!("{x:?}"); x }
// 输出: [Ok(1), Ok(11), Ok(1426), Ok(3)] fn list_of_results() -> Vec<Result<i32, DivisionError>> { let numbers = vec![27, 297, 38502, 81]; let division_results = numbers.into_iter().map(|n| divide(n, 27)); let x: Vec<Result<i32, DivisionError>> = division_results.collect(); println!("{x:?}"); x }
核心原因:collect的行为由目标类型决定
collect是迭代器的通用方法,它的行为完全取决于你指定的目标类型——不同类型实现了不同的FromIterator trait,collect就是调用这个trait的方法来生成目标值。
当目标类型是Result<Vec<i32>, DivisionError>时
Result类型的FromIterator实现做了"短路"处理:
- 遍历迭代器中的每个
Result元素,若所有元素都是Ok(value),就把所有value收集成Vec,最后返回Ok(该Vec) - 一旦遇到任何一个
Err(error),立刻停止遍历,直接返回这个Err(error),不会处理后续元素
当目标类型是Vec<Result<i32>, DivisionError>时
Vec类型的FromIterator实现逻辑很直接:
- 不管迭代器里的元素是
Ok还是Err,都会原样把每个Result元素收集到数组里,完整保留所有结果的状态
反例验证
如果把numbers里的某个数改成不能被27整除的(比如28):
result_with_list会直接返回Err(DivisionError),不会收集其他元素的结果list_of_results会返回[Ok(1), Err(DivisionError), Ok(1426), Ok(3)],保留所有迭代产生的Result状态
内容的提问来源于stack exchange,提问作者Bader
相关产品推荐
相关产品推荐

