我想使用collect()
a iterator of Result<T, E>
s into a Vec<T>
and early-return以防迭代器中的任何元素出错。所以,类似于这样:
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let input = ""; // Snip real input
let games: Vec<Game> = input.lines().map(parse_game).collect()?;
println!("parsed {} games", games.len());
Ok(())
}
struct Game;
fn parse_game(_s: &str) -> Result<Game, Box<dyn Error>> {
Ok(Game)
}
字符串
(Playground link,是的,代码的灵感来自于代码2023第2天的到来)
但这不起作用,它无法编译,并出现错误:
error[E0282]: type annotations needed
--> src/main.rs:5:58
|
5 | let games: Vec<Game> = input.lines().map(parse_game).collect()?;
| ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
|
help: consider specifying the generic argument
|
5 | let games: Vec<Game> = input.lines().map(parse_game).collect::<Vec<_>>()?;
| ++++++++++
型
如果我添加类型注解以在collect()
上使用正确的impl FromIterator
,它就可以工作:
let games: Vec<Game> = input.lines().map(parse_game).collect::<Result<_, _>>()?;
型
(Playground link)
但是我不明白为什么::<Result<_, _>>
的turbofish类型注解是必要的,而且我觉得它非常多余和嘈杂。
我希望Rust编译器知道parse_game
返回Result
s,如果我想收集到Vec<Game>
中,(由games
变量类型指定),我在返回Result
的函数上使用?
运算符提前返回(main()
),那么collect()
调用也应该返回Result
,因此不需要显式的类型注解。
那么,有没有一种方法可以去掉这个turbofish类型注解呢?或者用其他的习惯表达方式?
2条答案
按热度按时间6yt4nkrj1#
有很多方法可以去掉turbofish,但你不会喜欢它们。第一种方法是使用一个中间变量。
字符串
第二种方法是使用
collect
的内部trait函数FromIterator::from_iter
。型
第一个在噪音方面没有提供任何比turbofish更好的改进,第二个失去了
collect
的功能风格。不幸的是,我不认为有更好的方法来避免
collect
的turbofish,然而,itertools crate提供了try_collect
,它可以满足你的需要。型
mf98qq942#
我刚刚了解到有一个proposal for
Iterator::try_collect()
可以做到这一点,并且可以在Rust上每晚使用,作为一个不稳定的功能:字符串
(Playground link)
这不适用于那些只想使用稳定Rust的人(比如我),但如果你已经每晚都在使用,这可能是一个方便的功能。