rustreturnunwrap

Is there any way of doing unwrap_or_return an Error (any error)


Is there any way to simplify the returns in the following example (originally copied from here):

use std::num::ParseIntError;

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    let first_number = match first_number_str.parse::<i32>() {
        Ok(first_number)  => first_number,
        Err(e) => return Err(e),
    };

    let second_number = match second_number_str.parse::<i32>() {
        Ok(second_number)  => second_number,
        Err(e) => return Err(AnotherError::ParseError("error")),
    };

    Ok(first_number * second_number)
}

I mean something like:

use std::num::ParseIntError;

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
    let first_number = first_number_str.parse::<i32>()
        .unwrap_or_return(|e| Err(e));

    let second_number = second_number_str.parse::<i32>()
        .unwrap_or_return(|e| Err(AnotherError::ParseError("error"));

    Ok(first_number * second_number)
}

Solution

  • You're looking for the question mark operator, possibly combined with Result::or or Result::or_else, depending on the specifics of your use-case.

    That code example can be rewritten as

    use std::num::ParseIntError;
    
    pub fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
        let first_number = first_number_str.parse::<i32>()?;
        let second_number = second_number_str.parse::<i32>().or_else(|e| Err(e))?;
        // The closure in `or_else` could also return `Ok` or some different error with type `ParseIntError`.
        // let second_number = second_number_str.parse::<i32>().or_else(|_e| Ok(27))?;
    
        Ok(first_number * second_number)
    }
    

    (playground)

    If you know that you're going to return Ok in the or_else, Result::unwrap_or is more appropriate. Check out the other similar methods on Result to see what's offered.