 # Maths with Results

What's the best way to add/subtract/divide/multiply Results without many '?' marks (E.g. Result )? Is there a crate that implements a numeric type with arithmetic that propagates errors?

(maybe one that takes a num-trait as a type parameter ?)

I couldn't find something out there, but I'm sure someone must have already tried doing something like this?

I had a similar problem while implementing arithmetic ops for JSON data. I had to define it as

``````#[derive(Clone, Debug)]
pub enum Json {
Null,
Bool(bool),
Integer(Integral),
Float(Floating),
String(String),
Array(Vec<Json>),
Object(Vec<Property>),
// Hidden variants
#[doc(hidden)]
__Error(Error),
}
``````

If any operation in a JSON arithmetic expression fails, it will create an `__Error` variant and all parent operation will short circuit when one of its operand is `__Error` variant.

1 Like

You could try using the newtype pattern to define a wrapper over result and then implement standard arithmetic traits.
For example:

``````use std::ops::Add;

#[derive(Debug)]
struct MyResult(Result<f64, String>);

type Output = Self;
fn add(self, other: Self) -> Self::Output {
match (self, other) {
(MyResult(Ok(a)), MyResult(Ok(b))) => MyResult(Ok(a + b)),
_ => MyResult(Err(String::from("Can be handled better to propagate instead.")))
}
}
}

fn main() {
let a = MyResult(Ok(5.0));
let b = MyResult(Ok(2.0));
let c = a + b;
println!("{:?}", c);
}
``````
1 Like

If only one side is a `Result`, then `Result.map(|x| x + 2)` can do it. Otherwise, `?` is probably the way to go.

@BlueBlazin yeah that was kind of what I was thinking.
Just figured there must be a crate out there doing this already. There's likely to be a lot of maths so less friction the better.

If it can just look like maths that would be best. The ? marks also incur brackets. E.g. ((a + b)? + (c + d)?)?

Maybe I just retrofit the '?' with a math! macro...

@gilescope If you care about performance, you probably have to use `f32` or `f64`. They have `NaN`s which signal that a value is not valid. Unless you need specific error reasons, I would suggest to use `NaN` to your advantage.