β’ 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
match safe_div(10, 0) {
Ok(value) => println!("Got: {}", value),
Err(e) => println!("Failed: {:?}", e),
}
// Define what errors your function can produce
#[derive(Debug, PartialEq)]
enum MathError {
DivisionByZero,
NegativeSquareRoot,
}
// Return type says: "this can fail with MathError"
fn safe_div(a: i64, b: i64) -> Result<i64, MathError> {
if b == 0 {
Err(MathError::DivisionByZero) // wrap error in Err(...)
} else {
Ok(a / b) // wrap success in Ok(...)
}
}
// Pattern match to handle both cases
match safe_div(10, 2) {
Ok(v) => println!("{}", v), // prints 5
Err(e) => println!("{:?}", e),
}
// Utility methods for quick access
safe_div(10, 2).unwrap_or(0); // returns 5, or 0 if Err
safe_div(10, 0).is_err(); // true
safe_div(10, 2).ok(); // Some(5) β converts to Option
| Concept | OCaml | Rust | |
|---|---|---|---|
| Success value | `Ok value` | `Ok(value)` | |
| Failure value | `Error e` | `Err(e)` | |
| Pattern match | `match r with Ok v -> ... \ | Error e -> ...` | `match r { Ok(v) => ..., Err(e) => ... }` |
| Error type | Any type, often polymorphic `('a, 'b) result` | Must be concrete: `Result<T, E>` | |
| Ignoring errors | Compiler warns, but possible | Compiler error (unused `Result` triggers warning that's hard to ignore) | |
| Convert to Option | `Result.to_option` | `.ok()` | |
| Default on error | `Result.value ~default` | `.unwrap_or(default)` |
// Result Basics β 99 Problems #45
// Explore Result<T, E>: construction, matching, ok/err conversion.
#[derive(Debug, PartialEq)]
enum MathError {
DivisionByZero,
NegativeSquareRoot,
Overflow,
}
fn safe_div(a: i64, b: i64) -> Result<i64, MathError> {
if b == 0 {
Err(MathError::DivisionByZero)
} else {
Ok(a / b)
}
}
fn safe_sqrt(x: f64) -> Result<f64, MathError> {
if x < 0.0 {
Err(MathError::NegativeSquareRoot)
} else {
Ok(x.sqrt())
}
}
fn parse_int(s: &str) -> Result<i64, String> {
s.trim().parse::<i64>().map_err(|e| format!("parse error: {}", e))
}
fn main() {
// Basic Ok/Err
println!("safe_div(10, 2) = {:?}", safe_div(10, 2));
println!("safe_div(10, 0) = {:?}", safe_div(10, 0));
println!("safe_sqrt(9.0) = {:?}", safe_sqrt(9.0));
println!("safe_sqrt(-1.0) = {:?}", safe_sqrt(-1.0));
println!("parse_int('42') = {:?}", parse_int("42"));
println!("parse_int('abc') = {:?}", parse_int("abc"));
// Pattern matching
match safe_div(100, 4) {
Ok(v) => println!("100/4 = {}", v),
Err(e) => println!("Error: {:?}", e),
}
// ok() converts to Option
println!("ok(): {:?}", safe_div(10, 2).ok());
println!("ok() err: {:?}", safe_div(10, 0).ok());
// err() extracts the error as Option
println!("err(): {:?}", safe_div(10, 0).err());
// is_ok / is_err
println!("is_ok(10/2): {}", safe_div(10, 2).is_ok());
println!("is_err(10/0): {}", safe_div(10, 0).is_err());
// unwrap_or
println!("unwrap_or(0): {}", safe_div(10, 0).unwrap_or(0));
// unwrap_or_else
println!("unwrap_or_else: {}", safe_div(10, 0).unwrap_or_else(|_| -1));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ok() {
assert_eq!(safe_div(10, 2), Ok(5));
}
#[test]
fn test_err() {
assert_eq!(safe_div(10, 0), Err(MathError::DivisionByZero));
}
#[test]
fn test_sqrt_ok() {
assert_eq!(safe_sqrt(4.0), Ok(2.0));
}
#[test]
fn test_sqrt_err() {
assert_eq!(safe_sqrt(-1.0), Err(MathError::NegativeSquareRoot));
}
#[test]
fn test_ok_to_option() {
assert_eq!(safe_div(10, 2).ok(), Some(5));
assert_eq!(safe_div(10, 0).ok(), None);
}
#[test]
fn test_parse() {
assert!(parse_int("42").is_ok());
assert!(parse_int("abc").is_err());
}
}
(* Result Basics *)
(* OCaml 99 Problems #45 *)
(* Implementation for example 45 *)
(* Tests *)
let () =
(* Add tests *)
print_endline "β OCaml tests passed"