How to idomatically access field nested in a chain of Options?

Hi,
the question or thread title might be a bit confusing. However, l have a structure that contains optional fields that contain optional fields as well which lead to a kind of "options" chain when trying to access the contents of a specific nested field.

Example:

struct Foo {
  bar: Option<Bar>,
}

struct Bar {
  baz: Option<Baz>
}

struct Baz {
  field1: u32,
  field2: Option<u32>,
}

Accessing field1 based on Foo (assuming it is an option too) becomes a little cumbersome:

fn main() {
    let foo = Some(Foo {
        bar: Some(Bar {
            baz: Some(Baz {
                field1: 42,
                field2: None,
            })      
        })
    });
    
    let field1 = foo.map(|foo| foo.bar.map(|bar| bar.baz.map(|baz| baz.field1)));
    dbg!(&field1);
    dbg!(&field1.flatten());
    dbg!(&field1.flatten().flatten());
}

The number of flatten calls depend on the number of nestings of Options... the question is, if there is a better way to achieve this. Thus providing None if any step of the chain is None and Some(..) of the final field if we could reach it?

Use and_then instead of map. Or, if you have many levels of nesting, write a getter that uses ? to chain optionals:

impl Foo {
    fn field1(&self) -> Option<u32> {
        self.bar?.baz?.field1.into()
    }
}
4 Likes

You could use Option::and_then.

let field1 = foo
    .and_then(|foo| foo.bar)
    .and_then(|bar| bar.baz)
    .map(|baz| baz.field1);
dbg!(field1);