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!