rust 为什么hint类型不能和collect一起使用?只有turbofish语法?

wlp8pajw  于 2023-04-21  发布在  其他
关注(0)|答案(2)|浏览(105)

我只是发现了一些我认为不是那样的东西(事实上我浪费了很多时间来修复它)。
我想在你的帮助下了解我哪里错了,如果我理解正确。
所以我爱上了?错误处理(我不知道在其他语言中没有它我是如何生活的!)。
但是使用collect(),我认为是一样的:

pub fn get_players(input: &PlayerInput) -> Result<Option<Vec<Player>>> {
    if let Some(input_players) = input.players.as_ref() {
        let players: Result<Vec<Player>> = input_players
            .iter()
            .map(|x| {
                Player::new(x.id.as_deref(), &x.code, &x.name)
            })
            .collect()?;

        Ok(Some(players))
    } else {
        Ok(None)
    }
}

错误:

error[E0308]: mismatched types
   --> src\player\get.rs:55:17
    |
55  |         Ok(Some(players))
    |            ---- ^^^^^^^^ expected struct `Vec`, found enum `Result`
    |            |
    |            arguments to this enum variant are incorrect
    |
    = note: expected struct `Vec<_>`
                 found enum `Result<Vec<_>, common::error::Error>`
help: the type constructed contains `Result<Vec<Player>, common::error::Error>` due to the type of the argument passed
   --> src\player\get.rs:55:12
    |
55  |         Ok(Some(players))
    |            ^^^^^--------^
    |                 |
    |                 this argument influences the type of `Some`

所以阅读网页时,我发现我需要使用turbofish语法来使其工作,而不是类型提示,就像这样:

pub fn get_players(input: &PlayerInput) -> Result<Option<Vec<Player>>> {
    if let Some(input_players) = input.players.as_ref() {
        // let players: Result<Vec<Player>> = input_players
        let players = input_players
            .iter()
            .map(|x| {
                Player::new(x.id.as_deref(), &x.code, &x.name)
            })
            // .collect()?;
            .collect::<Result<Vec<Player>>>()?;

        Ok(Some(players))
    } else {
        Ok(None)
    }
}

但为什么会这样呢?为什么提示类型在这里不起作用呢?

9o685dep

9o685dep1#

使用?的事实使编译器变得模糊。多个类型可以使?适用于返回Result的函数:你可以编写自己的这样的类型(好吧,它需要nightly,因为Try trait是实验性的,但它是可能的)。因此,编译器认为你可能正在将collect()插入一个不同的类型,该类型也实现了FromIteratorTry

fnvucqvd

fnvucqvd2#

如果你使用的是?,这段代码需要更新,因为Result现在被分割成一个返回值,或者Ok部分被赋值。在?之后剩下的就是Ok部分:

let players: Vec<Player> = input_players // No longer Result<...>
    .iter()
    .map(|x| { ... })
    .collect()?;

如果你让编译器只使用let players = ...来解决这个问题,它可能会像预期的那样工作。
编译器说的是“我不知道如何从这个迭代器中收集Result”。
你可以在作业上暗示,或者在多宝鱼上暗示,或者两者都暗示,但是如果两者都暗示,他们必须就发生了什么达成一致。
编译器应该能够弄清楚players唯一可以是Vec<Player>,这应该是可行的,但如果不可行,那么就是提示时间了。

相关问题