Option, Result and the ? operator

Values that may be missing (Option) and operations that may fail (Result), handled with match, if let, unwrap_or and ?.

Runs in Zerethon IDE · Rust 1.87 Official Rust documentation ↗

Rust has no null and no exceptions. A value that may be absent is Option<T> (Some(v) or None); a result that may be an error is Result<T, E> (Ok(v) or Err(e)). The compiler makes you deal with both cases.

main.rs
use std::num::ParseIntError;

fn parse_sum(a: &str, b: &str) -> Result<i32, ParseIntError> {
    let x: i32 = a.trim().parse()?;
    let y: i32 = b.trim().parse()?;
    Ok(x + y)
}

fn first_even(numbers: &[i32]) -> Option<i32> {
    numbers.iter().copied().find(|n| n % 2 == 0)
}

fn main() {
    match parse_sum("3", " 4") {
        Ok(sum) => println!("sum = {sum}"),
        Err(e) => println!("error: {e}"),
    }
    if let Err(e) = parse_sum("3", "x") {
        println!("error: {e}");
    }
    println!("{:?} {:?}", first_even(&[1, 3, 4]), first_even(&[1, 3]));
    println!("{}", first_even(&[7]).unwrap_or(-1));
}

Output

sum = 7
error: invalid digit found in string
Some(4) None
-1
  • ? returns the error to the caller at once; it works in functions that themselves return Result (or Option).
  • .unwrap() and .expect("message") stop the program on None / Err — fine for quick experiments, not for input you do not control.
  • unwrap_or(default), unwrap_or_default() and map handle the missing case without stopping.