试图排出字符串并映射其字符但由于类型推断而失败

xet*_*a11 1 inference collect rust

这段代码(游乐场):

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

生成此错误:

<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
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题?

mal*_*rbo 6

您应该使用Iterator::fold而不是Iterator::collect:

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

Iterator::collect文件说:

将迭代器转换为集合.

并且Iterator::fold:

一个迭代器适配器,它应用一个函数,产生一个最终值.

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

观察:你的函数获取字符串的所有权,因此使用drain没有区别,因为字符串将被丢弃(感谢评论Matthieu M).如果你的意图是使用字符串,使其为空,但不取得所有权,你可以声明这样的函数:

fn resolve_score(string: &mut String) -> u16
Run Code Online (Sandbox Code Playgroud)

并使用drain,因此函数返回后字符串将为空.如果不需要使用该字符串,则可以接收&str参数:

fn resolve_score(string: &str) -> u16   
Run Code Online (Sandbox Code Playgroud)

另请注意,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
}
Run Code Online (Sandbox Code Playgroud)

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