-
Notifications
You must be signed in to change notification settings - Fork 542
Description
I am trying to do something like the code below which works fine if I choose to ignore the Err
coming out of fallible_calculation
. However, I do not know how to short-circuit the calculation and turn (Vec<T>, Vec<U>)
into Result<(Vec<T>, Vec<U>), E>
.
let res: (Vec<T>, Vec<U>) = us
.par_iter()
.partition_map(|u match fallible_calculation(u) {
Ok(t) if cond(t) => Either::Right(u.clone()),
Ok(t) => Either::Left(t),
Err(SpecificError) => Either::Right(u.clone()),
Err(e) => {},
});
How would I go about properly handling the error case? In the case of the map
adapter the issue is pretty straight forward, but I don't see how can be done in this case, other than maybe collecting to a (Vec<T>, Result<Vec<U>, E>>)
instead, which however doesn't seem to short circuit? That would look like so:
let res: (Vec<T>, Result<Vec<U>, E>) = us
.par_iter()
.partition_map(|u match fallible_calculation(u) {
Ok(t) if cond(t) => Either::Right(Ok(u.clone())),
Ok(t) => Either::Left(t),
Err(SpecificError) => Either::Right(Ok(u.clone())),
Err(e) => Either::Right(Err(e)),
});
Are there better ways?
EDIT: I didn't realize that Result<T, E>
doesn't implement Default
and ParallelExtend
, which means that this tactic unfortunately doesn't work either. :-(
EDIT: The fix that I could come up with to make this workable at all (albeit without short-circuiting) is this:
let (a, b, c): (Vec<T>, Vec<U>, Vec<E>) = us
.par_iter()
.partition_map(|u match fallible_calculation(u) {
Ok(t) if cond(t) => Either::Right(Ok(u.clone())),
Ok(t) => Either::Left(t),
Err(SpecificError) => Either::Right(Ok(u.clone())),
Err(e) => Either::Right(Err(e)),
});
if c.len() > 0 {
Err(c.swap_remove(0))?
}
It's not particularly elegant, but works.