When deserializing deeply nested structures (e.g. from JSON), it's not uncommon to have to traverse multiple Option
types.
For example:
let foo = Foo {
x: Some(Bar {
y: Some(Baz {
z: Some(42),
})
})
};
Is there an idiomatic way of chaining Option to access deeply nested values?
So far I have the following, but neither are as concise as foo.x?.y?.z
in other languages that support optional-chaining:
let z = foo.x.as_ref().and_then(|x| x.y.as_ref()).and_then(|y| y.z);
let z = foo.x.as_ref().and_then(|x| x.y.as_ref()?.z);
let z = (|| foo.x.as_ref()?.y.as_ref()?.z)();
It looks like the try_block
feature might be a good fit, but it's currently unstable.
let z = try { foo.x.as_ref()?.y.as_ref()?.z };
As you say, the try
block would be perfect for this.
In the meantime you can take advantage of the fact that ?
works in functions, and wrap your expression in a closure and call it:
let z = (|| foo.x.as_ref()?.y.as_ref()?.z )();
You can write a simple macro to make it a bit nicer:
macro_rules! tryit {
($($e: tt)+) => {
(|| { $($e)+ })()
}
}
Which works basically the same as the try
block:
let z = tryit! { foo.x.as_ref()?.y.as_ref()?.z };