Skip to content

partition_map with a fallible closure - how to shortcircuit? #801

@SuperFluffy

Description

@SuperFluffy

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions