| # `Result` |
| |
| We've seen that the `Option` enum can be used as a return value from functions |
| that may fail, where `None` can be returned to indicate failure. However, |
| sometimes it is important to express *why* an operation failed. To do this we |
| have the `Result` enum. |
| |
| The `Result<T, E>` enum has two variants: |
| |
| * `Ok(value)` which indicates that the operation succeeded, and wraps the |
| `value` returned by the operation. (`value` has type `T`) |
| * `Err(why)`, which indicates that the operation failed, and wraps `why`, |
| which (hopefully) explains the cause of the failure. (`why` has type `E`) |
| |
| ```rust,editable,ignore,mdbook-runnable |
| mod checked { |
| // Mathematical "errors" we want to catch |
| #[derive(Debug)] |
| pub enum MathError { |
| DivisionByZero, |
| NonPositiveLogarithm, |
| NegativeSquareRoot, |
| } |
| |
| pub type MathResult = Result<f64, MathError>; |
| |
| pub fn div(x: f64, y: f64) -> MathResult { |
| if y == 0.0 { |
| // This operation would `fail`, instead let's return the reason of |
| // the failure wrapped in `Err` |
| Err(MathError::DivisionByZero) |
| } else { |
| // This operation is valid, return the result wrapped in `Ok` |
| Ok(x / y) |
| } |
| } |
| |
| pub fn sqrt(x: f64) -> MathResult { |
| if x < 0.0 { |
| Err(MathError::NegativeSquareRoot) |
| } else { |
| Ok(x.sqrt()) |
| } |
| } |
| |
| pub fn ln(x: f64) -> MathResult { |
| if x <= 0.0 { |
| Err(MathError::NonPositiveLogarithm) |
| } else { |
| Ok(x.ln()) |
| } |
| } |
| } |
| |
| // `op(x, y)` === `sqrt(ln(x / y))` |
| fn op(x: f64, y: f64) -> f64 { |
| // This is a three level match pyramid! |
| match checked::div(x, y) { |
| Err(why) => panic!("{:?}", why), |
| Ok(ratio) => match checked::ln(ratio) { |
| Err(why) => panic!("{:?}", why), |
| Ok(ln) => match checked::sqrt(ln) { |
| Err(why) => panic!("{:?}", why), |
| Ok(sqrt) => sqrt, |
| }, |
| }, |
| } |
| } |
| |
| fn main() { |
| // Will this fail? |
| println!("{}", op(1.0, 10.0)); |
| } |
| ``` |