The code below reads numbers, sums them, then prints the sum. I've tried few annotations, but it didn't work. I must be missing something. How could I make it work?
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);
}
Error message from compiler:
type annotations needed
--> src\main.rs:9:10
|
9 | .filter_map(|w| w.parse().ok())
| ^^^^^^^^^^ cannot infer type for `B`
The quick fix is to say which type you are parsing into:
The reason is that
filter_map
has a type variableB
, which would need to be inferred from the closure that you pass to it (the closure returnsOption<B>
). However,parse()
also has a type variable for the type you are parsing into, which also can often be inferred. But here the type-checker would have to infer each of these types from each other, which obviously can't be done. To break the cycle, you have to tell it somewhere what the concrete type is.You also could have fixed it by annotating
filter_map
. It's not as nice becausefilter_map
has two type parameters, but you can still let the second one be inferred by using an_
:Let's look up the signature of filter_map to see, what the complain is about:
Okay, so
Option<B>
is the result, which means he cannot infer whatw.parse().ok()
will be.Let's try to give him a hint
Let's compile an see.... Hurray!
So, lesson learned: Look up the signature and try to figure out, which part the compiler cannot infer and try to specify it.