Match: Switch on Steroids

Welcome to Day 17! By now, we’ve covered some seriously cool Rust features, but today might be my favorite so far: the match expression. If you’re coming from a C# background—especially with the newer C# 8+ switch expressions—you might think you’ve seen it all. Trust me, Rust’s match is like a switch statement on steroids, protein shakes, and a Red Bull chaser.

Basic Match: Rust’s Superpowered Switch

In Rust, match is incredibly powerful and expressive. At its core, it’s used to match a value against multiple patterns. Think of it like a Swiss Army knife—it can handle anything from simple cases to complex scenarios with ease:

fn main() {
    let number = 4;

    match number {
        1 => println!("One!"),
        2 | 3 | 5 | 7 => println!("Prime"),
        4..=10 => println!("Between 4 and 10"),
        _ => println!("Something else"),
    }
}

Cool, right? Rust lets you handle multiple values (2 | 3 | 5 | 7) and even ranges (4..=10) with clean, concise syntax.

Pattern Matching vs. C# Switch Expressions

C# devs might recognize pattern matching from recent language updates. Let’s quickly remind ourselves of what C# 8+ switch expressions look like:

var number = 4;

var result = number switch
{
    1 => "One",
    2 or 3 or 5 or 7 => "Prime",
    >= 4 and <= 10 => "Between 4 and 10",
    _ => "Something else"
};

Console.WriteLine(result);

Both languages share similarities, but Rust’s match goes even further:

  • Exhaustive Checks: Rust enforces exhaustive pattern matching at compile-time. If you miss a case, Rust won’t compile until you handle every possible scenario.
  • Powerful Patterns: Rust can match complex data types, destructure tuples and structs, and even match on enum variants.

Advanced Match: Pattern Matching on Complex Types

Here’s where Rust really flexes its muscles:

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

enum UsState {
    Alabama,
    Alaska,
    // more states...
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);
            25
        },
    }
}

fn main() {
    let coin = Coin::Quarter(UsState::Alaska);
    println!("Value: {} cents", value_in_cents(coin));
}

This example demonstrates how match elegantly destructures and matches data within enums—something C# is starting to do but not yet as fluidly.

The Wildcard _ to the Rescue

One more powerful feature: Rust’s wildcard _. This ensures every case is covered without explicitly defining them all:

let some_number = Some(5);
match some_number {
    Some(7) => println!("Lucky number 7!"),
    _ => println!("Some other number"),
}

Why Rust’s Match Is a Game-Changer

  • Safety: You simply cannot miss a case by accident. Rust forces you to handle every scenario explicitly or use a wildcard.
  • Readability: Complex logic stays concise and clear.
  • Maintainability: Adding or modifying patterns is straightforward, making your code easy to evolve and understand.

Wrap-Up

Rust’s match isn’t just powerful—it’s addictive. Once you start using it, you’ll wonder how you ever managed complex branching logic without it. It’s more than just a switch statement; it’s pattern matching at its very best.

Tomorrow, we’ll push pattern matching even further with destructuring—prepare for another thrilling Rust adventure!

Share:

Leave a reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.