Pulling Results out of Options

The most basic way of handling mixed error types is to just embed them in each
other.

  1. use std::num::ParseIntError;
  2. fn double_first(vec: Vec<&str>) -> Option<Result<i32, ParseIntError>> {
  3. vec.first().map(|first| {
  4. first.parse::<i32>().map(|n| 2 * n)
  5. })
  6. }
  7. fn main() {
  8. let numbers = vec!["42", "93", "18"];
  9. let empty = vec![];
  10. let strings = vec!["tofu", "93", "18"];
  11. println!("The first doubled is {:?}", double_first(numbers));
  12. println!("The first doubled is {:?}", double_first(empty));
  13. // Error 1: the input vector is empty
  14. println!("The first doubled is {:?}", double_first(strings));
  15. // Error 2: the element doesn't parse to a number
  16. }

There are times when we’ll want to stop processing on errors (like with
?) but keep going when the Option is None. A
couple of combinators come in handy to swap the Result and Option.

  1. use std::num::ParseIntError;
  2. fn double_first(vec: Vec<&str>) -> Result<Option<i32>, ParseIntError> {
  3. let opt = vec.first().map(|first| {
  4. first.parse::<i32>().map(|n| 2 * n)
  5. });
  6. let opt = opt.map_or(Ok(None), |r| r.map(Some))?;
  7. Ok(opt)
  8. }
  9. fn main() {
  10. let numbers = vec!["42", "93", "18"];
  11. let empty = vec![];
  12. let strings = vec!["tofu", "93", "18"];
  13. println!("The first doubled is {:?}", double_first(numbers));
  14. println!("The first doubled is {:?}", double_first(empty));
  15. println!("The first doubled is {:?}", double_first(strings));
  16. }