# Enums, Option and Pattern Matching — Rust

Source: https://www.skillbyai.com/en/rust/t-enums

> 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.

```rust
#[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.

**Quiz:** How does Rust represent a value that may be absent?

- [ ] null
- [x] 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.
