SkillByAIOpen interactive version →

Lesson 12 / 25

Enums, Option and Pattern Matching

Model alternatives; no null.

Variants carry data

Rust enums list alternatives, and each variant can carry different data (Card { last4 }, Upi(String)). match handles every variant, binding their data. Rust has no null: optional values use Option<T> (Some(value) or None), so the compiler forces you to handle absence. if let handles one pattern concisely, and helpers such as unwrap_or, map and ? make Option ergonomic.

Payment variants and optional prices, run

I ran this with Rust 1.99.0 (cargo run, edition 2024, standard library only). describe matches each payment variant and extracts its data. find_price returns Some for known items and None for others; if let and unwrap_or handle the None case explicitly.

#[derive(Debug)]
enum Payment {
    Cash,
    Card { last4: String },
    Upi(String),
}

fn describe(p: &Payment) -> String {
    match p {                                   // match must cover every variant
        Payment::Cash => "cash".to_string(),
        Payment::Card { last4 } => format!("card ending {last4}"),
        Payment::Upi(id) => format!("UPI {id}"),
    }
}

fn find_price(item: &str) -> Option<u32> {
    match item {
        "pen" => Some(899),
        "notebook" => Some(120),
        _ => None,                              // no null: absence is a value
    }
}

fn main() {
    for p in [Payment::Cash, Payment::Card { last4: "4242".into() }, Payment::Upi("asha@okbank".into())] {
        println!("{}", describe(&p));
    }
    println!("{:?} {:?}", find_price("pen"), find_price("lamp"));
    if let Some(price) = find_price("notebook") {
        println!("notebook costs {price}");
    }
    println!("lamp or default: {}", find_price("lamp").unwrap_or(0));
}

Output:

cash
card ending 4242
UPI asha@okbank
Some(899) None
notebook costs 120
lamp or default: 0

Make invalid states unrepresentable

Model states as enum variants carrying exactly the data valid in that state, instead of structs with many optional fields.

Quick check: How does Rust represent a value that may be absent?

  • null
  • Option<T> with Some or None
  • An empty string
  • A special -1 value
Answer

Option<T> with Some or None — Absence is explicit in the type.