Before updating to a more recent Rust version the following used to work:
fn example(val: &[&str]) {
let parsed_value: Vec<usize> = val
.iter()
.filter_map(|e| e.parse::<usize>())
.collect();
}
However, now the parse method returns a Result
type instead of an Option
and I get the error:
error[E0308]: mismatched types
--> src/lib.rs:4:25
|
4 | .filter_map(|e| e.parse::<usize>())
| ^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
= note: expected type `std::option::Option<_>`
found type `std::result::Result<usize, std::num::ParseIntError>`
I could create an Option
through a conditional, but is there a better / cleaner way?
Use Result::ok
. Types added for clarity:
let res: Result<u8, ()> = Ok(42);
let opt: Option<u8> = res.ok();
println!("{:?}", opt);
For symmetry's sake, there's also Option::ok_or
and Option::ok_or_else
to go from an Option
to a Result
.
In your case, you have an iterator.
If you'd like to ignore failures, use Iterator::flat_map
. Since Result
(and Option
) implement IntoIterator
, this works:
let parsed_value: Vec<usize> = val
.iter()
.flat_map(|e| e.parse())
.collect();
If you'd like to stop on the first failure, you can collect
into one big Result
. This is less obvious, but you can check out the implementors of FromIterator
for the full list of collect
-able items.
let parsed_value: Result<Vec<usize>, _> = val
.iter()
.map(|e| e.parse())
.collect();
Of course, you can then convert the one big Result
into an Option
, as the first example shows.