I find myself regularly encountering the need for logic where two optional values should be "merged" where:
None
-> give me None
Some
-> give me Some
of thatSome
-> apply some function (T, T) -> T
and give me Some
of thatThis is useful for example when you want to keep the largest or smallest known value. I have not seen a method on Option
in the standard library that does this.
This is different from:
.zip()
results in None
if either option is None
whereas I want to keep the other one.or()
gives priority of the first over the second whereas I want to use a merging function in that caseThis can be done directly with a match
:
match (a_opt, b_opt) {
(Some(a), Some(b)) => Some(Ord::max(a, b)), // pick the largest
(Some(a), None) => Some(a),
(None, Some(b)) => Some(b),
(None, None) => None,
}
If I need this more than once I usually create my own function (sometimes as an extention method):
fn merge<T>(a: Option<T>, b: Option<T>, f: impl FnOnce(T, T) -> T) -> Option<T> {
match (a, b) {
(Some(a), Some(b)) => Some(f(a, b)),
(Some(a), None) => Some(a),
(None, Some(b)) => Some(b),
(None, None) => None,
}
}
merge(a_opt, b_opt, Ord::max)