SyntaxStudy
Sign Up
Rust Defining Enums and Match Expressions
Rust Beginner 1 min read

Defining Enums and Match Expressions

Enums in Rust are algebraic data types: each variant can carry different kinds and amounts of data. An enum variant can be unit-like (no data), tuple-like (anonymous fields), or struct-like (named fields). This makes Rust enums far more powerful than the simple integer enumerations found in C or Java, and they are the idiomatic way to represent values that can be one of several distinct cases. The `match` expression is the primary tool for destructuring enum values. Match arms must be exhaustive — every possible variant must be handled, or the compiler will reject the code. This exhaustiveness check prevents the common bug of forgetting to handle a new variant added to an enum. The `_` wildcard pattern handles any remaining cases, and `..` ignores named fields you do not need. Each arm of a `match` expression is itself an expression, so `match` can return a value. Combined with Rust's enum variants carrying data, this makes `match` the foundation of safe, expressive pattern matching. You can match on integers, strings, tuples, structs, enums, and nested combinations of all of these in a single `match` block.
Example
#[derive(Debug)]
enum Shape {
    Circle { radius: f64 },
    Rectangle { width: f64, height: f64 },
    Triangle(f64, f64, f64),  // three side lengths
}

impl Shape {
    fn area(&self) -> f64 {
        match self {
            Shape::Circle { radius } => std::f64::consts::PI * radius * radius,
            Shape::Rectangle { width, height } => width * height,
            Shape::Triangle(a, b, c) => {
                // Heron's formula
                let s = (a + b + c) / 2.0;
                (s * (s - a) * (s - b) * (s - c)).sqrt()
            }
        }
    }

    fn name(&self) -> &'static str {
        match self {
            Shape::Circle { .. } => "circle",
            Shape::Rectangle { .. } => "rectangle",
            Shape::Triangle(..) => "triangle",
        }
    }
}

fn main() {
    let shapes: Vec<Shape> = vec![
        Shape::Circle { radius: 5.0 },
        Shape::Rectangle { width: 4.0, height: 6.0 },
        Shape::Triangle(3.0, 4.0, 5.0),
    ];

    for s in &shapes {
        println!("{}: area = {:.4}", s.name(), s.area());
    }

    // Match with a guard
    let n = 7i32;
    let desc = match n {
        i if i < 0 => "negative",
        0 => "zero",
        i if i % 2 == 0 => "positive even",
        _ => "positive odd",
    };
    println!("{n} is {desc}");
}