Reputation: 653
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
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