H. Desane
H. Desane

Reputation: 653

How can I propagate the errors in Rust?

Is there a nice way to propagate errors in Rust? E. g., I'd like to refactor the following code to avoid nested errors:

.for_each(|record| {
    match f1() {
        Ok(a1) => match f2() {
            Ok(a2) => match f3() {
                Ok(_) => {}
                Err(e) => {
                    eprintln!("Error: {}", e);
                }
            },
            Err(e) => {
                eprintln!("Error: {}", e);
            }
        },
        Err(e) => {
            eprintln!("Error: {}", e);
        }
    };
    Ok(())
})

The question is not a duplicate because I've got a for_each operator which complicates a situation for me. And when I put ? to f2 I actually receive the following error:

the trait `std::convert::From<std::io::Error>` is not implemented for `grpcio::error::Error`

Upvotes: 0

Views: 1383

Answers (1)

Akiner Alkan
Akiner Alkan

Reputation: 6918

You can chain your functions in the success scenario with and_then and map their errors with map_err.

Like here you can chain them:

let result = f1().and_then(|_| {
    f2().and_then(|_| {
        f3().and_then(|_| {
            println!("All functions are succeed");
            Ok(())
        })
    })
});

Here you will have the result variable if the error occurs.

Then you can match this error with if let Err(error) statement like following:

if let Err(error) = result {
    println!("Problem occurred: {:?}", error);
};

There is also possibility to throw your error to upper levels with try! macro or ? operator like following:

fn throw_error() -> Result<String, MyError> {
    let string_val = "will not be returned".to_string();

    Err(MyError::thrownError)?;
    Ok(string_val)
}

Here you can test and play a little bit more to understand the concepts.

Upvotes: 3

Related Questions