---
title: "11.x Chapter 11 summary and quiz"
description: "Review of enums, data-carrying variants, Option, match in depth, destructuring, the if let family, and enum methods, with a chapter quiz and capstone."
url: "https://learnrust.net/chapter-11/chapter-11-summary-and-quiz/"
last_updated: "2026-06-13"
---

# 11.x Chapter 11 summary and quiz

Chapter 10 gave you "and" types; this chapter gave you "or" types and the pattern-matching machinery that makes them sing. Review, then a capstone that wires several pieces together.

## Quick review

An **enum** is a program-defined type whose value is exactly one of a fixed set of **variants** ([11.1](https://learnrust.net/chapter-11/enums/)). Reach for one whenever a value has a known set of states, especially where a `bool` is tempting but doesn't fit. The payoff is exhaustiveness: a `match` over an enum must handle every variant (E0004 otherwise), so adding a variant later turns every unhandled `match` into a compiler-assigned checklist. This is "make impossible states unrepresentable."

Variants can **carry data**, and different variants can carry different shapes: nothing, a tuple of values, or named fields ([11.2](https://learnrust.net/chapter-11/enums-with-data/)). An enum with data is "a value that is one of several shapes," the sum-type partner to chapter 10's product-type structs. You read the data back out by matching, never with a dot, because the data is only present in some variants.

**`Option<T>`** is the standard-library enum with variants `Some(T)` and `None`, Rust's replacement for null ([11.3](https://learnrust.net/chapter-11/option/)). Because `Option<T>` is a different type from `T`, the compiler forces you to handle absence before use, moving the null check from runtime hope to compile-time guarantee. `unwrap`/`expect` convert "maybe absent" into "present or panic" and are the long-promised explanation of the `.expect()` you've written since lesson [1.6](https://learnrust.net/chapter-1/reading-input/); prefer `match`, the `if let` family, or `unwrap_or` for `Option`s that can really be `None`.

**`match` in depth** ([11.4](https://learnrust.net/chapter-11/match-in-depth/)): patterns bind names (`Some(n)`), combine with `|`, test ranges with `..=`, carry extra conditions as **guards** (`if x > 0`), and bind-while-testing with `@`. The two catch-alls are `_` (ignore) and a bare name (bind), and they must come last. **Destructuring** ([11.5](https://learnrust.net/chapter-11/destructuring/)) is the same patterns aimed at taking compound values apart, in `match`, in `let`, and in function parameters; construction and destructuring are mirror images. A `let` pattern must match every value, which is why `let Some(x) = ...;` is refused.

That refusal motivates three lighter tools ([11.6](https://learnrust.net/chapter-11/if-let-while-let-let-else/)): **`if let`** for one pattern (plus optional `else`), **`while let`** for looping until a pattern fails, and **`let else`** for bind-or-bail early exit. Each is a `match` with the boilerplate removed; use them for readability, use `match` when you want every case checked. Finally, enums take **methods** via `impl` just like structs, and the `match self` shape inside them models state machines, where variants are states, carried data is per-state data, and methods are transitions ([11.7](https://learnrust.net/chapter-11/methods-on-enums/)).

## Quiz time

**Question #1**

When should you reach for an enum instead of a struct? Give the one-sentence test.

<details class="solution">
<summary>Show solution</summary>

Use an enum when a value is exactly *one of* a fixed set of alternatives (the "or" question); use a struct when a value's parts all coexist (the "and" question). A traffic light is one of red/yellow/green: enum. A point has both an x and a y: struct.

</details>

**Question #2**

For each, say what it prints or why it's refused:

a)

```rust
let x: Option<i32> = Some(4);
let y = x + 1;
```

b)

```rust
let x: Option<i32> = Some(4);
println!("{}", x.unwrap_or(0));
```

c)

```rust
let x: Option<i32> = None;
if let Some(n) = x {
    println!("{n}");
} else {
    println!("none");
}
```

<details class="solution">
<summary>Show solution</summary>

a) Refused, E0277: `Option<i32>` is not `i32`, so you can't add 1 to it; you must handle the `None` case first. b) Prints `4`: `unwrap_or` returns the contained value since it's `Some`. c) Prints `none`: `x` is `None`, the `if let` pattern doesn't match, so the `else` runs.

</details>

**Question #3**

What does this print?

```rust
fn classify(n: i32) -> &'static str {
    match n {
        0 => "zero",
        x if x < 0 => "negative",
        1..=9 => "small",
        big @ 10..=99 => return_label(big),
        _ => "huge",
    }
}

fn return_label(_n: i32) -> &'static str {
    "medium"
}

fn main() {
    println!("{}", classify(-5));
    println!("{}", classify(7));
    println!("{}", classify(50));
    println!("{}", classify(1000));
}
```

<details class="solution">
<summary>Show solution</summary>

```
negative
small
medium
huge
```

`-5` fails `0`, matches the guard `x < 0`. `7` matches `1..=9`. `50` matches `big @ 10..=99`, binding `50` and passing it to `return_label`, which returns `"medium"`. `1000` falls through to `_`. (The `&'static str` return type is the whole-program lifetime of string literals from lesson [9.5](https://learnrust.net/chapter-9/dangling-references/).)

</details>

**Question #4**

The capstone. Model a vending machine as a state machine. Define an enum `Machine` with variants `Waiting`, `Collecting { inserted: u32 }` (cents inserted so far), and `Dispensing { item: String }`. Write:

- a method `insert(self, cents: u32) -> Machine` that, from `Waiting` or `Collecting`, adds to the inserted total and returns `Collecting` (from any other state, returns `self` unchanged);
- a method `status(&self) -> String` describing the current state;
- in `main`, start at `Waiting`, insert 75 then 50, and print the status after each step.

<details class="solution">
<summary>Show solution</summary>

```rust
#[derive(Debug)]
enum Machine {
    Waiting,
    Collecting { inserted: u32 },
    Dispensing { item: String },
}

impl Machine {
    fn insert(self, cents: u32) -> Machine {
        match self {
            Machine::Waiting => Machine::Collecting { inserted: cents },
            Machine::Collecting { inserted } => {
                Machine::Collecting { inserted: inserted + cents }
            }
            other => other,
        }
    }

    fn status(&self) -> String {
        match self {
            Machine::Waiting => String::from("insert coins"),
            Machine::Collecting { inserted } => format!("{inserted} cents in"),
            Machine::Dispensing { item } => format!("dispensing {item}"),
        }
    }
}

fn main() {
    let mut machine = Machine::Waiting;
    println!("{}", machine.status());

    machine = machine.insert(75);
    println!("{}", machine.status());

    machine = machine.insert(50);
    println!("{}", machine.status());
}
```

```
insert coins
75 cents in
125 cents in
```

Design notes. `insert` takes `self` by value (not `&self`) because it consumes the old state and returns a new one, which is the state-machine transition shape; that's why `main` reassigns `machine` each step and needs a `mut` binding. Inserting 75 from `Waiting` gives `Collecting { inserted: 75 }`, and inserting another 50 gives `Collecting { inserted: 125 }`. The `other => other` arm forwards any unhandled state unchanged, and `status` takes `&self` because it only reads. The `Dispensing` variant is unused in this run but completes the machine; a fuller version would transition into it once `inserted` reaches an item's price.

</details>

You now hold both halves of Rust's type-building toolkit: structs for "and", enums for "or", and `match` to take either apart safely. Chapter 12 spends that toolkit on the problem it was secretly built for. `Result`, the enum hiding inside every `parse` and `read_line` you've written, becomes error handling you design deliberately, with the `?` operator turning pages of boilerplate into a single character.

## Sitemap

See the full [sitemap](https://learnrust.net/sitemap.md) for all pages.
