无法为filter_map()。sum()推断B的类型

时间:2018-07-11 10:41:10

标签: parsing types rust type-inference

下面的代码读取数字,将它们求和,然后打印总和。我尝试了一些注释,但是没有用。我肯定错过了什么。我该如何运作?

use std::io;
use std::io::Read;

fn main() {
    let mut buff = String::new();
    io::stdin().read_to_string(&mut buff).expect("read_to_string error");

    let v: i32 = buff
        .split_whitespace()
        .filter_map(|w| w.parse().ok())
        .sum();

    println!("{:?}", v);
}

来自编译器的错误消息:

type annotations needed
 --> src\main.rs:9:10
  |
9 |         .filter_map(|w| w.parse().ok())
  |          ^^^^^^^^^^ cannot infer type for `B`

2 个答案:

答案 0 :(得分:3)

让我们查找filter_map的签名以查看投诉内容:

fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where F: FnMut(Self::Item) -> Option<B>, 

好吧,所以Option<B>是结果,这意味着他无法推断w.parse().ok()是什么。

让我们给他一个提示

.filter_map(|w| w.parse::<i32>().ok())

我们来编译一下。。。。

因此,我们吸取了教训:查找签名并尝试找出编译器无法推断的那部分,并尝试指定它。

答案 1 :(得分:2)

快速解决方案是说您要解析为哪种类型:

let v: i32 = buff
    .split_whitespace()
    .filter_map(|w| w.parse::<i32>().ok())
    .sum();

原因是filter_map有一个类型变量B,需要从传递给它的闭包中推断出来(闭包返回Option<B>)。但是,parse()还具有要解析为的类型的类型变量,通常也可以推断出该类型变量。但是在这里,类型检查器将不得不相互推断出每种类型,这显然是不可能做到的。要打破循环,您必须在某个地方告诉它具体的类型。

您也可以通过注释filter_map来修复它。不太好,因为filter_map有两个类型参数,但是您仍然可以使用_来推断第二个参数:

let v: i32 = buff
    .split_whitespace()
    .filter_map::<i32, _>(|w| w.parse().ok())
    .sum();