无法推断 filter_map().sum() 的“B”类型

Dul*_*gon 3 parsing types type-inference rust

下面的代码读取数字,对它们求和,然后打印总和。我尝试了一些注释,但没有成功。我肯定错过了什么。我怎样才能让它发挥作用?

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

来自编译器的错误消息:

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

hel*_*low 6

让我们查看filter_map的签名,看看抱怨的内容是什么:

fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where F: FnMut(Self::Item) -> Option<B>, 
Run Code Online (Sandbox Code Playgroud)

好吧,Option<B>结果也是如此,这意味着他无法推断w.parse().ok()会发生什么。

我们试着给他一个提示

.filter_map(|w| w.parse::<i32>().ok())
Run Code Online (Sandbox Code Playgroud)

让我们编译一下看看……万岁!

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

  • @hellow:我不认为这是原因。`w.parse::&lt;u32&gt;()` 和 `.sum::&lt;u64&gt;()` [不会编译](https://play.rust-lang.org/?gist=51e381197289b22dea66b1b4b35b01df&amp;version=stable&amp;mode=debug&amp;edition =2015)。我认为这与“sum()”不返回求和类型(称为“Item”)而是返回任何实现“Sum&lt;Item&gt;”的值这一事实更相关。并且编译器会失败,因为可以应用任意数量的类型。 (2认同)