I have code like this:
let things = vec![/* ...*/]; // e.g. Vec<String> things .map(|thing| { let a = try!(do_stuff(thing)); Ok(other_stuff(a)) }) .filter(|thing_result| match *thing_result { Err(e) => true, Ok(a) => check(a), }) .map(|thing_result| { let a = try!(thing_result); // do stuff b }) .collect::<Result<Vec<_>, _>>()
In terms of semantics, I want to stop processing after the first error.
The above code works, but it feels quite cumbersome. Is there a better way? I've looked through the docs for something like filter_if_ok
, but I haven't found anything.
I am aware of collect::<Result<Vec<_>, _>>
, and it works great. I'm specifically trying to eliminate the following boilerplate:
match
on thing_result
. I feel like this should just be a one-liner, e.g. .filter_if_ok(|thing| check(a))
.map
, I have to include an extra statement let a = try!(thing_result);
in order to deal with the possibility of an Err
. Again, I feel like this could be abstracted away into .map_if_ok(|thing| ...)
.Is there another approach I can use to get this level of conciseness, or do I just need to tough it out?
There are lots of ways you could mean this.
If you just want to panic, use .map(|x| x.unwrap())
.
If you want all results or a single error, collect
into a Result<X<T>>
:
let results: Result<Vec<i32>, _> = result_i32_iter.collect();
If you want everything except the errors, use .filter_map(|x| x.ok())
or .flat_map(|x| x)
.
If you want everything up to the first error, use .scan((), |_, x| x.ok())
.
let results: Vec<i32> = result_i32_iter.scan((), |_, x| x.ok());
Note that these operations can be combined with earlier operations in many cases.
Since Rust 1.27, Iterator::try_for_each
could be of interest:
An iterator method that applies a fallible function to each item in the iterator, stopping at the first error and returning that error.
This can also be thought of as the fallible form of
for_each()
or as the stateless version oftry_fold()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With