代码之家  ›  专栏  ›  技术社区  ›  Dulguun Otgon

无法为filter_map().sum()推断'b'的类型

  •  2
  • Dulguun Otgon  · 技术社区  · 6 年前

    下面的代码读取数字,求和,然后打印总和。我试过一些注释,但没用。我一定错过了什么。我怎么能让它工作?

    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 回复  |  直到 6 年前
        1
  •  2
  •   Peter Hall    6 年前

    快速修复方法是说要分析到哪种类型:

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

    原因是 filter_map 具有类型变量 B ,这需要从传递给它的闭包中推断(闭包返回 Option<B> )然而, parse() 对于要解析到的类型,也有一个类型变量,这通常也是可以推断的。但在这里,类型检查器必须互相推断这些类型中的每一个,这显然是不可能的。要打破这个循环,你必须告诉它具体的类型是什么。

    你也可以通过注释来修复它。 过滤图 . 不是很好,因为 过滤图 有两个类型参数,但仍可以使用 _ :

    let v: i32 = buff
        .split_whitespace()
        .filter_map::<i32, _>(|w| w.parse().ok())
        .sum();
    
        2
  •  3
  •   hellow Adolfo Casari    6 年前

    让我们查一下过滤器地图的签名,看看有什么问题:

    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())
    

    让我们编译一个see…。万岁!

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