Switch types of Result? Result<T, E> -> Result<E, T>?

Is there a one liner to turn a Result<T, E> into a Result<E, T>, i.e.

fn swap(self) -> Result<E, T>
    match self {
        Ok(t) => Err(t),
        Err(e) => Ok(e),
    }
}

in a library? Why doesn't this exist in the standard library (or does it)?

Your match is fine. It is not provided in std just because it's not a common requirement. Maybe there is a crate for that, I don't know, but I wouldn't bother. Just write a generic function or even an extension trait.

I often wanted this because I sometimes want to chain this function behind a function returning a result, most commonly in something like try_fold. This can be used to search a collection by mapping elements to Err to break out of the function, but return a default if no element is found. The Result is Err when an element was found, and Ok if the default is returned. afterwards it would be nice to simply swap the Ok and Err values to use it more conventionally. wrapping the result in a match expression requires some more complex code formatting:

iter.try_fold(...)
    .swap()

vs

match iter.try_fold(...) {
    ...
}

Well, this is actually kind of abusing Result. I mean, this is the best we have today, but it will be more correctly resolved by using std::ops::ControlFlow with its (unstable) methods (e.g. break_value() or map_break()).

2 Likes

Because putting an error type in the Ok variant, or a non-error in the Err variant, is an anti-pattern.

This is exactly the situation for which ControlFlow::Break was added: https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#the-opscontrolflow-type

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.