繁体   English   中英

如何确定Rust迭代器的结果类型?

[英]How to determine the resulting type of a Rust iterator?

我正在通过沙沙练习来学习Rust。 我已经达到了iterator3.rs练习并陷入困境。 本练习要求我提供一行代码,作为操作的一部分,它将结果从一种类型映射到另一种类型。 我需要使用正确的操作填写x =行。 有两个部分-第一部分:

let numbers = vec![27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
let x = ???
assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])");

下一个是相同的,但声明输出的格式略有不同:

assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");

我相信我知道第一个实例需要返回一个包含i32的Vector或某种错误类型的Result。 第二个需要返回每个都有i32或错误类型的结果向量。

但是,我通常很难理解如何确定into_iter,map和collect的组合返回的类型。 在学习如何推理或获得编译器帮助时,我可以使用一些帮助。

这是我到目前为止的位置:

我不明白除法结果的结果类型是什么。 我试图使用编译器错误消息以及该问题的答案来找出答案 ,但结果对我而言是不透明的,这可能是由于延迟评估所致。 例如,仅将x替换为divide_results,以便assert将显示类型,如下所示:

assert_eq!(format!("{:?}", division_results), "Ok([1, 11, 1426, 3])");

给我这个结果:

left: `"Map { iter: IntoIter([27, 297, 38502, 81]) }"`,
right: `"Ok([1, 11, 1426, 3])"`', exercises/standard_library_types/iterator3.rs:75:9

由于迭代和映射尚未发生,因此尚不清楚左侧结果是什么。 我尝试过的其他各种方法也提供了类似的结果。

考虑到问题是懒惰的评估,我还尝试使用collect来查看是否会强制评估。 例如,在divide_results行的末尾调用collect,如下所示:

division_results = numbers.into_iter().map(|n| divide(n, 27)).collect();

提供错误:

cannot infer type consider giving `division_results` a type

当我修改收集说:

let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<i32>();

我收到一个错误,以为我提示了正确的类型:

let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<i32>();
   |                                                                           ^^^^^^^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=std::result::Result<i32, DivisionError>>`

所以我尝试了错误消息中显示的类型:

let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<Result<i32, DivisionError>>();

只得到这个错误:

let division_results = numbers.into_iter().map(|n| divide(n, 27)).collect::<Result<i32, DivisionError>>();
   |                                                                           ^^^^^^^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`

显然我缺少了一些东西。 也许你能告诉我什么?

迭代器适配器上的map()方法; 它接受一个迭代器,然后返回另一个迭代器,但它本身不会消耗原始迭代器的任何项目。 返回类型Map是原始迭代器的包装,当使用每个项目时,该迭代器将提供的闭包应用于每个项目。

如果您希望Map实际执行某项操作,则需要使用迭代器。 最常见的方法是for循环和collect()方法(但是还有许多其他消耗迭代器的方法,例如sum()count()fold()max() …)。 在这种情况下,最合适的方法是调用collect()方法,因为您希望将结果收集到向量中。

你已经计算出,为所期望的类型x是一个Result包裹的向量i32或错误,或Result<Vec<i32>, DivisionError>鲁斯特语法。 由于collect()可以产生许多不同的返回类型,因此我们需要告诉编译器我们想要哪种类型。 一种方法是显式指定x的类型:

let x: Result<Vec<i32>, DivisionError> = division_results.collect();

这使用FromIterator特性实现,该特性允许将Result的可迭代集合收集到ResultResult封装了值的集合

您提到的另一种情况非常相似。 这次,目标类型是Result实例的向量,因此您所需要做的就是指定其他类型。 这将自动为您选择正确的FromIterator实现:

let x: Vec<Result<i32, DivisionError>> = division_results.collect();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM