21.6 Matching Enums

match is particularly powerful with enums, allowing clean handling of different variants and their associated data.

enum AppEvent {
    KeyPress(char),
    Click { x: i32, y: i32 },
    Quit,
}

fn handle_event(event: AppEvent) {
    match event {
        AppEvent::KeyPress(c) => { // Destructure the char
            println!("Key pressed: '{}'", c);
        }
        AppEvent::Click { x, y } => { // Destructure fields using punning
            println!("Mouse clicked at ({}, {})", x, y);
        }
        AppEvent::Quit => {
            println!("Quit event received.");
        }
    }
}

fn main() {
    handle_event(AppEvent::KeyPress('q'));
    handle_event(AppEvent::Click { x: 100, y: 250 });
    handle_event(AppEvent::Quit);
}

Matching Result<T, E> follows the same principle:

fn divide(numerator: f64, denominator: f64) -> Result<f64, String> {
    if denominator == 0.0 {
        Err("Division by zero".to_string())
    } else {
        Ok(numerator / denominator)
    }
}

fn main() {
    let result1 = divide(10.0, 2.0);
    match result1 {
        Ok(value) => println!("Result: {}", value),        // Output: Result: 5
        Err(msg) => println!("Error: {}", msg),
    }

    let result2 = divide(5.0, 0.0);
    match result2 {
        Ok(value) => println!("Result: {}", value),
        Err(msg) => println!("Error: {}", msg),         // Output: Error: Division by zero
    }
}

Again, the compiler enforces that both Ok and Err variants are handled.