?

Chaining results using match can get pretty untidy; luckily, the ? operator
can be used to make things pretty again. ? is used at the end of an expression
returning a Result, and is equivalent to a match expression, where the
Err(err) branch expands to an early Err(From::from(err)), and the Ok(ok)
branch expands to an ok expression.

  1. mod checked {
  2. #[derive(Debug)]
  3. enum MathError {
  4. DivisionByZero,
  5. NonPositiveLogarithm,
  6. NegativeSquareRoot,
  7. }
  8. type MathResult = Result<f64, MathError>;
  9. fn div(x: f64, y: f64) -> MathResult {
  10. if y == 0.0 {
  11. Err(MathError::DivisionByZero)
  12. } else {
  13. Ok(x / y)
  14. }
  15. }
  16. fn sqrt(x: f64) -> MathResult {
  17. if x < 0.0 {
  18. Err(MathError::NegativeSquareRoot)
  19. } else {
  20. Ok(x.sqrt())
  21. }
  22. }
  23. fn ln(x: f64) -> MathResult {
  24. if x <= 0.0 {
  25. Err(MathError::NonPositiveLogarithm)
  26. } else {
  27. Ok(x.ln())
  28. }
  29. }
  30. // Intermediate function
  31. fn op_(x: f64, y: f64) -> MathResult {
  32. // if `div` "fails", then `DivisionByZero` will be `return`ed
  33. let ratio = div(x, y)?;
  34. // if `ln` "fails", then `NonPositiveLogarithm` will be `return`ed
  35. let ln = ln(ratio)?;
  36. sqrt(ln)
  37. }
  38. pub fn op(x: f64, y: f64) {
  39. match op_(x, y) {
  40. Err(why) => panic!(match why {
  41. MathError::NonPositiveLogarithm
  42. => "logarithm of non-positive number",
  43. MathError::DivisionByZero
  44. => "division by zero",
  45. MathError::NegativeSquareRoot
  46. => "square root of negative number",
  47. }),
  48. Ok(value) => println!("{}", value),
  49. }
  50. }
  51. }
  52. fn main() {
  53. checked::op(1.0, 10.0);
  54. }

Be sure to check the documentation,
as there are many methods to map/compose Result.