Is it possible to express "result 1 if okay or result 2" as a chain of combinators?

Viewed 57

Imagine I have two functions which return Results and would like to select the first result if Ok and otherwise the second result. Something like the following:

fn primary() -> Result<String, ()> {
    Err(())
}

fn alternative() -> Result<String, ()> {
    Ok("alternative".to_string())
}

fn using_match() -> Result<String, ()> {
    Ok(match primary() {
        Ok(string) => string,
        _ => alternative()?
    })
}

I'm struggling to find a way to express this as a chain of combinators. The following doesn't work for the reason stated in the comment, but it captures the chain structure I'm trying to achieve:

fn combinator_attempt() -> Result<String, ()> {
    // this is wrong because the closure must return a String
    //                                               v----------------v
    Ok(primary().map(|string| string).unwrap_or_else(|_| alternative()?))
}

Is there an idiomatic way to express this? For extra points, what is a good way to select the first Ok (or last Err) from a chain of (three or more) possible operations?

EDIT: In case it helps anyone in the future, my issue here was a failure to think about the problem as, "let's do a series of operations on Results which yield Results. Instead, I was trying to unwrap the inner data or otherwise operate on another Result. The key, which I now understand thanks to @stepan's answer, is type continuity along the entire chain until the end.

1 Answers
Related