Oliver Jumpertz

Unpack Nested Results

Category: Rust

Share this snippet to:

let x: Result<Result<u32, &'static str>, &'static str> = Ok(Ok(1));
assert_eq!(Ok(1), x.flatten());
let x: Result<Result<u32, &'static str>, &'static str> = Ok(Err("Failure"));
assert_eq!(Err("failure"), x.flatten());
let x: Result<Result<u32, &'static str>, &'static str> = Err("Failure");
assert_eq!(Err("failure"), x.flatten());

Warning

Result::flatten currently is unstable and requires the nightly version of Rust to run.

Context

Nested Results can quickly become an issue in Rust. Rust has neither Exceptions nor Errors. Instead, Rust has its enum Result, which is basically an Either type that either contains a success case or an error case. But due to this, sometimes, you have to deal with nested Results. In this case, your code can quickly become pretty bloated.

You can go from this:

let x: Result<Result<u32, &'static str>, &'static str> = Ok(Ok(1));
match x {
Ok(x) => match x {
Ok(x) => handleX(x),
Err(e) => doSomethingWithError(e),
},
Err(e) => doSomethingWithError(e),
}

to this:

let x: Result<Result<u32, &'static str>, &'static str> = Ok(Ok(1));
let x = x.flatten();
match x {
Ok(x) => handleX(x),
Err(e) => doSomethingWithError(e),
}

Or from this:

let x: Result<Result<u32, &'static str>, &'static str> = Ok(Ok(1));
let x = x.map(|x| x.map(|x| x + 1));
let x = x.unwrap_or_else(|_: &str| Ok(0)).unwrap_or_else(|_| 0);

to this:

let x: Result<Result<u32, &'static str>, &'static str> = Ok(Ok(1));
let x = x.flatten();
let x: Result<u32, &'static str> = x.map(|x| x + 1);
let x = x.unwrap_or_default();

Share this snippet to: