Powerful Pattern Matching
Master `match` expressions and other pattern matching constructs for concise and exhaustive handling of data variants.
Powerful Pattern Matching is a free Learn Rust Coding lesson on CoddyKit — lesson 3 of 3. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Learn Rust Coding learning path, one of 3 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Unleashing Pattern Matching
Welcome to the world of pattern matching in Rust! This powerful feature allows you to control program flow based on the structure of data.
Instead of just checking equality, you can deconstruct values, extract components, and execute specific code for different data shapes.
- It's like a super-powered
if/elseorswitchstatement. - Ensures exhaustiveness: you must handle all possible patterns.
- Makes code more readable and robust.
The `match` Expression Basics
The core of pattern matching is the match expression. It takes a value and compares it against a series of patterns. The first pattern that matches wins!
Each 'arm' of a match expression consists of a pattern and the code to execute if that pattern matches.
enum Direction {
North,
East,
South,
West,
}
fn main() {
let my_direction = Direction::North;
match my_direction {
Direction::North => println!("Going up!"),
Direction::East => println!("Going right!"),
Direction::South => println!("Going down!"),
Direction::West => println!("Going left!"),
}
}Matching Literals and Ranges
You can match against specific literal values (numbers, characters, booleans) or define ranges using ..=. The | operator allows matching multiple patterns with a single arm.
Remember, patterns are checked in order, and the first match is used.
fn main() {
let x = 7;
match x {
1 => println!("It's one!"),
2 | 3 => println!("It's two or three!"),
4..=8 => println!("It's between four and eight!"),
_ => println!("It's something else!"), // Catch-all
}
let character = 'b';
match character {
'a'..='e' => println!("Early letter"),
_ => println!("Other letter"),
}
}Destructuring Structs
Pattern matching really shines when destructuring complex data types like structs. You can extract individual fields directly into variables within the match arm.
This makes accessing struct data clean and concise, especially when matching specific field values.
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 0, y: 7 };
match p {
Point { x, y: 0 } => println!("On the X axis at {}", x),
Point { x: 0, y } => println!("On the Y axis at {}", y),
Point { x, y } => println!("Not on an axis: ({}, {})", x, y),
}
}Destructuring Enums with Data
Enums in Rust can hold associated data. Pattern matching is the primary way to extract this data from an enum variant.
You can destructure the data directly into new variables, making it easy to work with the content of each variant.
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn process_message(msg: Message) {
match msg {
Message::Quit => println!("Quit message."),
Message::Move { x, y } => {
println!("Move to x: {}, y: {}", x, y);
}
Message::Write(text) => println!("Text message: {}", text),
Message::ChangeColor(r, g, b) => {
println!("Color: R:{}, G:{}, B:{}", r, g, b);
}
}
}
fn main() {
process_message(Message::Move { x: 10, y: 20 });
process_message(Message::Write(String::from("Hello!")));
}The Wildcard Pattern `_`
The special _ (underscore) pattern acts as a catch-all. It matches any value and does not bind to that value.
It's useful when you need to cover all possibilities for exhaustiveness but don't care about the specific value that matches a particular arm.
fn main() {
let some_value = Some(5);
let absent_value: Option<i32> = None;
match some_value {
Some(x) => println!("Got a value: {}", x),
_ => println!("Something else!"), // Matches None too
}
match absent_value {
Some(x) => println!("Got a value: {}", x),
_ => println!("No value here!"),
}
}`if let` for Single Patterns
Sometimes, you only care about matching one specific pattern and want to ignore all others. For these cases, if let is a more concise alternative to a full match expression.
It essentially says: "if this pattern matches, then do this; otherwise, do nothing (or execute an optional else block).".
fn main() {
let config_max = Some(3u8);
let none_value: Option<u8> = None;
if let Some(max) = config_max {
println!("Max configured to be: {}", max);
}
if let Some(val) = none_value {
println!("This won't print: {}", val);
} else {
println!("No value found!");
}
}`while let` for Conditional Loops
Similar to if let, while let allows you to loop as long as a pattern continues to match.
This is extremely useful for processing items from collections like Vecs where you want to continue until there are no more matching elements (e.g., until pop() returns None).
fn main() {
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
println!("Popped: {}", top);
}
println!("Stack is empty now.");
}Match Guards: Adding Conditions
You can add an additional if condition, called a match guard, to a match arm. The pattern must match AND the guard condition must be true for that arm to execute.
This allows for more fine-grained control within a pattern, without needing to create more enum variants.
fn main() {
let num = Some(4);
match num {
Some(x) if x % 2 == 0 => println!("Even number: {}", x),
Some(x) if x < 5 => println!("Small odd number: {}", x),
Some(x) => println!("Any other number: {}", x),
None => println!("No number"),
}
}Pattern Matching Challenge
Consider the following Rust code snippet. Which of the following statements about the match expression and its output are TRUE?
enum Status {
Loading,
Success(u32),
Error(String),
}
fn process_status(s: Status) {
match s {
Status::Success(code) if code > 200 => println!("Success with high code: {}", code),
Status::Success(code) => println!("Success with code: {}", code),
Status::Error(msg) => println!("Failed: {}", msg),
_ => println!("Status unknown or loading..."),
}
}
fn main() {
process_status(Status::Success(201));
process_status(Status::Error(String::from("Network issue")));
process_status(Status::Loading);
process_status(Status::Success(200));
}Recap: Mastering Patterns
You've explored the incredible power of pattern matching in Rust! It's a fundamental concept for writing clear, concise, and safe code.
matchexpressions provide exhaustive control flow based on data structure.- You can match literals, ranges, and use wildcards (
_). - Destructuring allows extracting values from structs and enums directly.
if letandwhile letoffer concise ways to match single patterns.- Match guards add conditional logic to
matcharms.
Keep practicing these patterns; they're essential for idiomatic Rust!
Frequently asked questions
Is the “Powerful Pattern Matching” lesson free?
Yes — the full text of “Powerful Pattern Matching” is free to read here on the web, and the Learn Rust Coding course includes 3 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Learn Rust Coding course, upgrade to CoddyKit PRO.
What will I learn in “Powerful Pattern Matching”?
Master `match` expressions and other pattern matching constructs for concise and exhaustive handling of data variants. You practise Learn Rust Coding with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Learn Rust Coding?
No prior experience is required. Learn Rust Coding on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 3, so you can start here or from the beginning and move at your own pace.
How long does the “Powerful Pattern Matching” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Learn Rust Coding lesson?
Yes. Every Learn Rust Coding lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Defining and Using Structs
- Enums for Custom Types
- Powerful Pattern Matching