Style question: Update variable based on an Option value

which one of these is "better" if you want to update a bunch of variables based on optional inputs from user (or parsing a, say, config file)

let mut config = default();
let opt: Option<T> = read_input();

// 1
config = if let Some(v) = opt {
    v
};

// 2
if opt.is_some() {
    config = opt.unwrap();
}

// 3
opt.map(|v| config = v);

// 4
config = *opt.get_or_insert(config);

// 5
config = opt.map_or_else(|| config, |v| v);

// 6
opt.and_then(|v| {
    config = v;
    Some(())
});

// 7
config = match opt {
    Some(v) => v,
    _ => config,
}
let config = read_input().unwrap_or_default();

Yes, good one. But in my case it's not that simple:

config is a struct with multiple fields, and I want to update the fields based on optional values:

struct Config {
    tags: u8,
    name: String,
    shared: bool,
    // ...
}

Right now I have something like this:

opt_1.map(|val| config.tags = val);
opt_2.map(|val| config.name = val);

I guess I'll have to implement Default for each field then.

You could write a helper function to factor out the boilerplate:

config.tags.update(opt_1);
config.name.update(opt_2);

The helper function could be something like this:

trait OptionalUpdate: Sized {
    fn update(&mut self, opt: Option<Self>) {
        opt.map(|val| *self = val);
    }
}

impl<T> OptionalUpdate for T {}
2 Likes

thanks, neat solution.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.