试图耗尽一个字符串并映射到它的字符上,但由于类型推断而失败

Trying to drain a string and map on its chars but failing because of type inference

此代码(Playground):

fn resolve_score(string: String) -> u16 {
    let mut score: u16;
    string
        .drain(..)
        .map(|char| {
            match char {
                'a' => score += 1,
                'f' => score += 4,
                _ => ()
            };
        })
        .collect();
}

生成此错误:

<anon>:16:14: 16:21 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
<anon>:16             .collect();
                       ^~~~~~~
<anon>:16:14: 16:21 help: see the detailed explanation for E0282
error: aborting due to previous error

我该如何解决这个问题?

你应该使用 Iterator::fold instead of Iterator::collect:

fn resolve_score(string: String) -> u16 {
    string.chars().fold(0, |mut score, char| {
        match char {
            'a' => score += 1,
            'f' => score += 4,
            _ => (),
        }
        score
    })
}

Iterator::collect 文档说:

Transforms an iterator into a collection.

Iterator::fold:

An iterator adaptor that applies a function, producing a single, final value.

在您的代码中,您有兴趣生成单个最终值 (score),而不是一个集合,因此 fold 更合适。

观察结果:您的函数拥有字符串的所有权,因此使用 drain 没有任何区别,因为无论如何都会删除该字符串(感谢评论 Matthieu M).如果您打算使用字符串,使其为空,但不获取所有权,则可以这样声明函数:

fn resolve_score(string: &mut String) -> u16

并使用drain,所以字符串在函数returns之后为空。如果不需要消费字符串,可以接收一个&str参数:

fn resolve_score(string: &str) -> u16   

另请注意,collect 失败是因为无法推断要生成哪个集合。你可以这样写:

fn resolve_score(string: String) -> u16 {
    let mut score: u16 = 0;
    string.chars()
        .map(|char| {
            match char {
                'a' => score += 1,
                'f' => score += 4,
                _ => (),
            };
        })
        .collect::<Vec<_>>();
    score
}

但这会很奇怪,因为您不会使用结果集合(空值)。