Currently updating the inner value of an Option<T> require a lot of boilerplace:
let mut value = Some(24);
if let Some(x) = value.as_mut() {
*x += 10;
}
or
value.as_mut().map(|x| {
*x += 10;
x
});
I propose to add an Option::update which allow to mutate the inner value with a function:
impl<T> Option<T> {
/// Updates the value of the option if is `Some`.
pub fn update<F>(&mut self, f: F) where F: FnOnce(T) -> T {
match self.take() {
Some(x) => {
let new_value = f(x);
self.replace(new_value);
},
None => {},
}
}
}
This is a good addition, but it would be even better if *value += 10 just worked and did nothing for None.
Since adding the Deref impl would probably cause issues,*value.entry() += 10 could be a middle ground.
Now, the issue is what exactly Option::entry would return.
I don't think that could work because of how those operators work. Furthermore, it isn't clear what should happen for None since there could be two actions. So it isn't very explicit.
FWIW, this doesn't need to return x unless you're chaining it to something further. You can even let += return directly for an unused Option<()>, and this auto-formats nicely:
I think it's clear what should happen with None: it stays None. That's because this is operating in Ts and if you have None there is no T to operate with.
It's theoretically possible but extremely dumb IMHO and probably would act extremely unexpectedly outside of trivial cases. TL;DR, struct OptionOpAssign<T>(Option<T>), deref to that via pointer cast, impl OpAssign traits for &mut OptionOpAssign<T>. Congrats, you've lifted OpAssign over Option, but you also have a completely meaningless non-mut deref, a bunch of extra types, and have to evaluate the rhs even if the option is None.