One of several solutions presented, now with impl OptionExtension.
Adapted from the solution presented by Shepmaster:
pub trait OptionExtension<T> {
fn combine_with<U, R, F>(self, other: Option<U>, f: F) -> Option<R>
where
F: Fn(T, U) -> R;
fn combine_with_sum<U, R>(self, other: Option<U>) -> Option<R>
where
T: std::ops::Add<U, Output = R>;
fn combine_with_mul<U, R>(self, other: Option<U>) -> Option<R>
where
T: std::ops::Mul<U, Output = R>;
}
impl<T> OptionExtension<T> for Option<T> {
fn combine_with<U, R, F>(self, other: Option<U>, f: F) -> Option<R>
where
F: Fn(T, U) -> R,
{
self.zip(other).map(|(x, y)| f(x, y))
}
fn combine_with_sum<U, R>(self, other: Option<U>) -> Option<R>
where
T: std::ops::Add<U, Output = R>
{
let sum = |a, b| {a + b};
self.combine_with(other, sum)
}
fn combine_with_mul<U, R>(self, other: Option<U>) -> Option<R>
where
T: std::ops::Mul<U, Output = R>
{
let mul = |a, b| {a * b};
self.combine_with(other, mul)
}
}
Other operations can also be added, such as fn combine_with sub, div, ...
See the Rust Playground.
And the main() function:
fn main() {
let a: Option<f64> = Some(5.0);
let b: Option<f64> = Some(10.0);
let c: Option<f64> = None;
let result_sum_ab = a.combine_with_sum(b);
let result_sub_ab = a.combine_with_sub(b);
let result_mul_ab = a.combine_with_mul(b);
let result_div_ab = a.combine_with_div(b);
assert_eq!(result_sum_ab, Some(15.0));
assert_eq!(result_sub_ab, Some(-5.0));
assert_eq!(result_mul_ab, Some(50.0));
assert_eq!(result_div_ab, Some(0.5));
println!("result_sum_ab: {:?}", result_sum_ab);
println!("result_sub_ab: {:?}", result_sub_ab);
println!("result_mul_ab: {:?}", result_mul_ab);
println!("result_div_ab: {:?}", result_div_ab);
let result_sum_ac = a.combine_with_sum(c);
let result_mul_ac = a.combine_with_mul(c);
assert_eq!(result_sum_ac, None);
assert_eq!(result_mul_ac, None);
println!("result_sum_ac: {:?}", result_sum_ac);
println!("result_mul_ac: {:?}", result_mul_ac);
}
The output:
result_sum_ab: Some(15.0)
result_sub_ab: Some(-5.0)
result_mul_ab: Some(50.0)
result_div_ab: Some(0.5)
result_sum_ac: None
result_mul_ac: None