โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
let ok: Result<i32, &str> = Ok(42);
let err: Result<i32, &str> = Err("oops");
// .ok() โ Option<T>: keeps value, discards error
ok.ok() // โ Some(42)
err.ok() // โ None
// .err() โ Option<E>: keeps error, discards value
ok.err() // โ None
err.err() // โ Some("oops")
// Common use: filter_map to skip errors
let results = vec![Ok(1), Err("bad"), Ok(3)];
let values: Vec<i32> = results.into_iter().filter_map(|r| r.ok()).collect();
// โ [1, 3]
// Chaining combinators
Ok(5_i32)
.map(|x| x * 2) // Ok(10)
.and_then(|x| if x > 5 { Ok(x) } else { Err("too small") })
.unwrap_or(0); // โ 10
| Concept | OCaml | Rust |
|---|---|---|
| Result โ Option (value) | `Option.of_result` / pattern match | `result.ok()` |
| Result โ Option (error) | Pattern match | `result.err()` |
| Transform value | `Result.map` | `result.map(f)` |
| Transform error | `Result.map_error` | `result.map_err(f)` |
| Chain operations | `Result.bind` / `let*` | `result.and_then(f)` |
| Fallback on error | Manual match | `result.or_else(f)` |
//! # Exhaustive Result/Option Method Survey
//!
//! Complete reference of `Result<T,E>` and `Option<T>` methods.
/// Demonstrate Result methods
pub fn result_methods() {
let ok: Result<i32, &str> = Ok(5);
let err: Result<i32, &str> = Err("bad");
// Query methods
let _ = ok.is_ok();
let _ = ok.is_err();
let _ = ok.ok();
let _ = err.err();
// Transform methods
let _ = ok.map(|x| x * 2);
let _ = err.map_err(|e| format!("error: {}", e));
let _ = ok.map_or(0, |x| x + 1);
let _ = ok.map_or_else(|_| 0, |x| x);
// Combinators
let _ = ok.and(Ok::<i32, &str>(10));
let _ = err.or(Ok::<i32, &str>(42));
let _ = ok.and_then(|x| Ok::<i32, &str>(x * 2));
let _ = err.or_else(|_| Ok::<i32, &str>(99));
// Unwrap variants
let _ = ok.unwrap_or(0);
let _ = ok.unwrap_or_else(|_| 0);
let _ = ok.unwrap_or_default();
}
/// Demonstrate Option methods
pub fn option_methods() {
let some: Option<i32> = Some(5);
let none: Option<i32> = None;
// Query methods
let _ = some.is_some();
let _ = none.is_none();
// Transform methods
let _ = some.map(|x| x * 2);
let _ = some.filter(|&x| x > 3);
let _ = some.map_or(0, |x| x + 1);
// Combinators
let _ = some.and(Some(10));
let _ = none.or(Some(42));
let _ = some.and_then(|x| Some(x * 2));
let _ = none.or_else(|| Some(99));
// Unwrap variants
let _ = none.unwrap_or(0);
let _ = none.unwrap_or_else(|| 99);
let _ = none.unwrap_or_default();
// Conversion
let _ = none.ok_or("missing");
let _ = Some(Some(42)).flatten();
let _ = some.zip(Some("hello"));
}
#[cfg(test)]
mod tests {
#[test]
fn test_result_map_chain() {
let r: Result<i32, &str> = Ok(5);
assert_eq!(r.map(|x| x * 2).map(|x| x + 1), Ok(11));
}
#[test]
fn test_option_and_then_chain() {
let r = Some(5i32)
.and_then(|x| if x > 0 { Some(x * 2) } else { None })
.filter(|&x| x < 20);
assert_eq!(r, Some(10));
}
#[test]
fn test_result_or_else() {
let r: Result<i32, &str> = Err("bad");
assert_eq!(r.or_else(|_| Ok::<i32, &str>(42)), Ok(42));
}
#[test]
fn test_option_zip() {
assert_eq!(Some(1).zip(Some("a")), Some((1, "a")));
assert_eq!(Some(1).zip(None::<&str>), None);
}
#[test]
fn test_option_flatten() {
assert_eq!(Some(Some(42)).flatten(), Some(42));
assert_eq!(Some(None::<i32>).flatten(), None);
}
}
(* 315. Exhaustive Result/Option method survey - OCaml *)
let () =
let ok_5 : (int, string) result = Ok 5 in
let err : (int, string) result = Error "bad" in
let some_5 = Some 5 in
let none : int option = None in
(* Result methods *)
Printf.printf "is_ok: %b %b\n" (Result.is_ok ok_5) (Result.is_ok err);
Printf.printf "is_error: %b %b\n" (Result.is_error ok_5) (Result.is_error err);
Printf.printf "map Ok: %s\n"
(match Result.map (fun x -> x * 2) ok_5 with Ok n -> string_of_int n | Error e -> e);
Printf.printf "map_error: %s\n"
(match Result.map_error (fun e -> "prefix: " ^ e) err with
| Ok n -> string_of_int n | Error e -> e);
Printf.printf "value: %d\n" (Result.get_ok ok_5);
(* Option methods *)
Printf.printf "is_some: %b %b\n" (Option.is_some some_5) (Option.is_some none);
Printf.printf "value: %d\n" (Option.value some_5 ~default:0);
Printf.printf "map: %d\n" (Option.fold ~none:0 ~some:(fun x -> x * 2) some_5);
Printf.printf "bind: %s\n"
(match Option.bind some_5 (fun x -> if x > 0 then Some (x + 1) else None) with
| Some n -> string_of_int n | None -> "None")