🎓 A1Learner
🔍

Rust Option

Option is a value that is either Some(value) or None. Its methods work with the value inside without a match for every step.

map changes the value inside

map runs your function only when a value is present. A None passes through untouched:

let name = Some("ada");
let loud = name.map(|n| n.to_uppercase());
println!("{loud:?}");

and_then chains a step that can fail

When the next step itself returns an Option, and_then feeds the value straight through. The answer stays one layer flat:

let boosted = Some(4).and_then(|n| if n > 0 { Some(n * 10) } else { None });
println!("{boosted:?}");

map would nest the box

The same step through map wraps its answer in a second Some — a box inside a box. That nesting is what and_then exists to avoid:

let boxed = Some(4).map(|n| if n > 0 { Some(n * 10) } else { None });
println!("{boxed:?}");

filter can turn a Some into a None

filter keeps the value only when a test passes. This age fails the test, so the Option becomes empty:

let age = Some(15).filter(|a| *a >= 18);
println!("{age:?}");

? leaves early on None

Inside a function that returns Option, ? hands the value out — or returns None at once when there is none. Sending the empty case onward like this is called propagation:

fn shout_first(word: Option<&str>) -> Option<String> {
    let w = word?;
    Some(w.to_uppercase())
}
let loud = shout_first(Some("hey"));
println!("{loud:?}");

Example

fn find_user(id: u32) -> Option<&'static str> {
    match id { 1 => Some("ada"), 2 => Some("grace"), _ => None }
}
fn main() {
    let shout = find_user(2).map(|n| n.to_uppercase());
    println!("{:?}", shout);
    println!("{:?}", find_user(9).unwrap_or("guest"));
}

Key points

  • Every Option answers one question: is there a value inside, or not?
  • Functions return Option instead of fake values like -1 or an empty string

In this example, find_user returns Some("grace") for id 2. Calling .map on it runs the function only because a value is present. The name becomes uppercase. The result is Some("GRACE"). For id 9, find_user returns None. unwrap_or("guest") steps in with the fallback, so the program prints "guest". No match was needed, and no empty box ever caused a crash.

Note

unwrap() also takes the value out.

unwrap() stops the program on None.

Keep it for quick tests and cases that truly cannot be empty.

Prefer unwrap_or in real code.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

Which method changes the value inside a Some and leaves None alone?