Oliver Jumpertz

Unpack Nested Options

Category: Rust

Share this snippet to:

let x: Option<Option<u32>> = Some(Some(1));
let x = x.flatten();
assertEq!(Some(1), x);
let x: Option<Option<u32>> = Some(None);
let x = x.flatten();
assertEq!(None, x);
let x: Option<Option<u32>> = None;
let x = x.flatten();
assertEq!(None, x);

Context

Nested Options can quickly become an issue in Rust. As the language has no null or nil, Option is the default way to deal with the absence of values. This, however, quickly leads to Options being passed around, even as parameters, and most functions accepting an Option will either only map the Option, or wrap it again. In the latter case, flattening Options can prevent some really dirty-looking code.

You can go from this:

let x: Option<Option<u32>> = Some(Some(1));
match x {
Some(x) => match x {
Some(x) => handleX(x),
None => doSomethingInCaseOfNone(),
},
None => doSomethingInCaseOfNone(),
}

to this:

let x: Option<Option<u32>> = Some(Some(1));
let x = x.flatten();
match x {
Some(x) => handleX(x),
None => doSomethingInCaseOfNone(),
}

Or from this:

let x: Option<Option<u32>> = Some(Some(1));
let x = x.map(|x| x.map(|x| x + 1));
let x = x.unwrap_or_default().unwrap_or_default();

to this:

let x: Option<Option<u32>> = Some(Some(1));
let x = x.flatten().map(|x| x + 1);
let x = x.unwrap_or_default();

Share this snippet to: