Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Types and Error Handling  ›  Lesson

Option and Result

Option and Result Enumerations 15 minOption says a value might be missing and Result says an operation might fail, and Rust makes you handle both cases before you can use the value.

Option and Result

Search the catalogue for a title it does not hold. Type letters where a card number should go. Many languages answer with null or an exception that the caller may forget to handle. Rust has neither. It uses two ordinary enums, and the type system will not let you ignore them.

The rule

Maybe missing → Option; might fail → Result. Handle both arms before use.

Both are enums from the standard library, always in scope:

enum Option<T> { Some(T), None }
enum Result<T, E> { Ok(T), Err(E) }

Option<T>: a value that may be absent, with no reason needed.

fn find(shelf: &[Book], title: &str) -> Option<usize> {
    shelf.iter().position(|b| b.title == title)
}

Result<T, E>: an operation that can fail, and E says why.

let card: Result<u32, _> = "1042".parse::<u32>();   // Ok(1042)
let bad: Result<u32, _> = "10x2".parse::<u32>();    // Err(ParseIntError)

An Option<u32> is not a u32. You cannot add to it or print it as a number until you open it:

match "10x2".parse::<u32>() {
    Ok(card) => println!("lending to card {card}"),
    Err(e) => println!("that is not a card number: {e}"),
}

if let Some(i) = find(&shelf, "Iron Tides") {
    println!("found at position {i}");
}

Handy methods instead of a full match:

  • unwrap_or(default): the value, or a fallback. input.parse::<u32>().unwrap_or(0).
  • unwrap(): the value, or panic (crash) on None/Err.
  • expect("message"): like unwrap, with your message in the panic.
  • ok() turns a Result into an Option; ok_or(err) goes the other way.

The shortcut

Ask: "If it isn't there, is that an error with a reason?" No reason needed → Option. A reason the caller should see → Result. Then choose how to open it: match or if let to handle, unwrap_or to default, ? (next lesson) to pass upward.

Lending by card numberStep 1 of 4
  1. Parse the input

    "1042".parse::<u32>() can fail with a reason, so it gives a Result.

The trap is unwrap() everywhere. It compiles, then crashes the first time real input is wrong.

Drills

Answer fast — trust the rule.

quick drill

What are the two variants of Result<T, E>?

quick drill

A catalogue search finds no match. Which return type fits best?

quick drill

What does "10x2".parse::<u32>().unwrap() do?

quick drill

What is "abc".parse::<u32>().unwrap_or(0)?

quick drill

With let n: Option<u32> = Some(5);, why does n + 1 fail to compile?

Remember

  • Option = Some or None (maybe missing); Result = Ok or Err (might fail, with a reason).
  • Ask "is absence an error with a reason?" Then open with match, if let, unwrap_or or ?.
  • Trap: unwrap turns a handled case into a crash.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainMissing or failed?

The library has fn find(title: &str) -> Option<Book> and fn parse_card(input: &str) -> Result<u32, ParseIntError>. Explain why one returns Option and the other Result, how a caller handles each with match, and why unwrap is risky.