It will be convenient to have f(&mut self, optb: Option<T>)
version of Option<T>
's f(self, optb: Option<T>) -> Option<T>
methods, especially when an option is a field of a struct.
Do you have specific examples? Most of the time, it works to call option.as_mut()
first.
trait OrSelf<T> {
fn or_self(&mut self, optb: Option<T>);
}
impl<T> OrSelf<T> for Option<T> {
fn or_self(&mut self, optb: Option<T>) {
match self {
Some(_) => {},
None => {
let _ = core::mem::replace(self, optb);
}
}
}
}
// for more complex types we can use or_else_self, concept is the same
type SomeProp = bool;
struct List {
prop: Option<SomeProp>,
items: Vec<Item>,
}
struct Item {
prop: Option<SomeProp>,
}
impl List {
fn apply_list_prop(&mut self) {
for item in &mut self.items {
item.prop.or_self(self.prop);
}
}
}
Side note: Instead of
let _ = core::mem::replace(self, optb);
you can just write
*self = optb;
so the implementation could become
impl<T> OrSelf<T> for Option<T> {
fn or_self(&mut self, optb: Option<T>) {
if self.is_none() {
*self = optb;
}
}
}
In general, it’s also possible to call the existing Option
methods relatively easily using the .take()
method, e.g. – demonstrated as an alternative implementation of OrSelf
:
impl<T> OrSelf<T> for Option<T> {
fn or_self(&mut self, optb: Option<T>) {
*self = self.take().or(optb)
}
}
Of course, it’d be interesting to check whether this optimizes properly or if there’s any overhead left.
1 Like
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.