filter_map can be used to reduce simple cases of mapping then filtering. In your example there is some logic to the filter so I don't think it simplifies things. I don't see any useful functions in the documentation for Result
either unfortunately. I think your example is as idiomatic as it could get, but here are some small improvements:
let things = vec![...]; // e.g. Vec
things.iter().map(|thing| {
// The ? operator can be used in place of try! in the nightly version of Rust
let a = do_stuff(thing)?;
Ok(other_stuff(a))
// The closure braces can be removed if the code is a single expression
}).filter(|thing_result| match *thing_result {
Err(e) => true,
Ok(a) => check(a),
}
).map(|thing_result| {
let a = thing_result?;
// do stuff
b
})
The ?
operator can be less readable in some cases, so you might not want to use it.
If you are able to change the check
function to return Some(x)
instead of true, and None
instead of false, you can use filter_map
:
let bar = things.iter().filter_map(|thing| {
match do_stuff(thing) {
Err(e) => Some(Err(e)),
Ok(a) => {
let x = other_stuff(a);
if check_2(x) {
Some(Ok(x))
} else {
None
}
}
}
}).map(|thing_result| {
let a = try!(thing_result);
// do stuff
b
}).collect::, _>>();
You can get rid of the let a = try!(thing);
by using a match in some cases as well. However, using filter_map
here doesn't seem to help.