我想使用s 到 acollect()的迭代器并提前返回,以防迭代器中的任何元素出错。所以,像这样:Result<T, E>Vec<T>
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)
}
Run Code Online (Sandbox Code Playgroud)
(Playground 链接,是的,该代码的灵感来自于 Advent of Code 2023 day 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<_>>()?;
| ++++++++++
Run Code Online (Sandbox Code Playgroud)
如果我添加类型注释以使用正确的impl FromIteratoron collect(),它会起作用:
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<_>>()?;
| ++++++++++
Run Code Online (Sandbox Code Playgroud)
(游乐场链接)
但我不明白为什么这种涡轮鱼类型注释::<Result<_, _>>是必要的。我发现它非常多余而且吵闹。
我希望 Rust 编译器知道parse_game返回Results,并且如果我想收集到 a Vec<Game>(由变量类型指定games)并且我提前返回返回( )?的函数上的运算符,那么调用也应该返回,因此不需要显式类型注释。Resultmain()collect()Result
那么,有没有办法摆脱这个turbofish类型注释呢?或者其他一些惯用的表达方式?
有很多方法可以摆脱涡轮鱼,但你不会喜欢它们。第一种方法是使用中间变量。
let games_result: Result<_, _> = input.lines().map(parse_game).collect();
let games: Vec<Game> = games_result?;
Run Code Online (Sandbox Code Playgroud)
第二种方法是使用 的collect内部特征函数FromIterator::from_iter。
let games: Vec<Game> = Result::from_iter(input.lines().map(parse_game))?;
Run Code Online (Sandbox Code Playgroud)
第一个在噪音方面没有比涡轮鱼有任何改进,第二个则失去了 的功能风格collect。
不幸的是,我认为没有更好的方法来避免涡轮鱼collect。然而, itertools crate 提供了try_collect,它可以满足您的需求。
use itertools::Itertools;
let games: Vec<Game> = input.lines().map(parse_game).try_collect()?;
Run Code Online (Sandbox Code Playgroud)