What is Pattern Matching?
Pattern Matching in Rust means checking a value against different possible shapes (patterns) and then running code depending on which one matches. The following tools were used for this:
- match: It is a very powerful tool that checks all possible cases. Forces you to handle every possibility (safe).
- if let: it’s a short and simple pattern that is used when you only care about one pattern and don’t want to write the full match.
The Syntax of Pattern Matching
Basic Syntax of match:
match value {
pattern1 => action1,
pattern2 => action2,
_ => default_action,
}
- value: The value we are checking.
- pattern: The shape or condition we want to check.
- action: The code executed if the pattern matches.
- _: A catch-all pattern for unmatched cases.
Simple Example of Pattern Matching
fn main() {
let score = Some(85);
// Using match
match score {
Some(mark) if mark >= 90 => println!("Excellent!"),
Some(mark) if mark >= 75 => println!("Good job!"),
Some(mark) => println!("You passed with {} marks.", mark),
None => println!("No score available."),
}
// Using if let (shorter way)
if let Some(mark) = score {
println!("Your score is {}.", mark);
}
}
Output
Good job!
Your score is 85.
Methods of pattern matching
1) Basic Match
fn main() {
let number = 2;
match number {
1 => println!("One"),
2 => println!("Two"),
3 => println!("Three"),
_ => println!("Something else"),
}
}
Output:
Two
2) Matching with Ranges
Matching with ranges means checking whether a value lies within a continuous sequence of numbers using the . .= operator inside a match expression.
fn main() {
let number = 15;
match number {
1..=10 => println!("Between 1 and 10"),
11..=20 => println!("Between 11 and 20"),
_ => println!("Outside the range"),
}
}
Output:
Between 11 and 20
3) Matching Enums
When you use pattern matching with enums, you check which variant the enum currently holds and then run code specific to that variant.
enum Weather {
Sunny,
Rainy,
Cloudy,
}
fn main() {
let today = Weather::Rainy;
match today {
Weather::Sunny => println!("Wear sunglasses"),
Weather::Rainy => println!("Take an umbrella"),
Weather::Cloudy => println!("Maybe it will rain, be prepared"),
}
}
Output:
Take an umbrella
4) Matching with Tuples
Tuples can also be destructured using patterns.
fn main() {
let coordinates = (3, 7);
match coordinates {
(0, 0) => println!("Origin"),
(x, 0) => println!("Point on X-axis at {}", x),
(0, y) => println!("Point on Y-axis at {}", y),
(x, y) => println!("Point at ({}, {})", x, y),
}
}
Output:
Point at (3, 7)
5) Ignoring Values with _
The _ pattern matches any value and can be used to ignore values.
For example:
fn main() {
let data = (10, 20);
match data {
(x, _) => println!("First value is {}", x),
}
}
Output:
First value is 10
6) Destructuring Structs
Pattern matching can destructure structs to access their fields. For example:
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 5, y: 10 };
match point {
Point { x, y: 0 } => println!("Point on X-axis at {}", x),
Point { x: 0, y } => println!("Point on Y-axis at {}", y),
Point { x, y } => println!("Point at ({}, {})", x, y),
}
}
Output:
Point at (5, 10)
7) Using Guards in Patterns
A guard is an extra condition you add to a match arm using if.
- First, Rust checks the pattern.
- Then, if the pattern matches, the guard condition is also checked.
- If the guard is true → that arm runs.
- If the guard is false → Rust continues checking the next arm.
fn main() {
let number = 15;
match number {
n if n % 2 == 0 => println!("Even number: {}", n),
n if n % 2 != 0 => println!("Odd number: {}", n),
_ => println!("No match"),
}
}
Output:
Odd number: 15
Using if let for Simpler Matches
if let is a shortcut for match when you only care about one specific pattern. Instead of writing a full match block, you can use if let to make the code shorter and cleaner.
fn main() {
let number = Some(5);
if let Some(value) = number {
println!("The value is {}", value);
} else {
println!("No value");
}
}
Output:
The value is 5
Advanced Concepts in Pattern Matching
1) Combining Patterns with | (OR Pattern)
When you want one action to happen for multiple values, you can combine patterns using |.
fn main() {
let day = "Saturday";
match day {
"Saturday" | "Sunday" => println!("It's the weekend!"),
"Monday" | "Friday" => println!("Busy weekday!"),
_ => println!("Just a normal day."),
}
}
Output:
It's the weekend!
- “Saturday” | “Sunday” means → if the day is Saturday OR Sunday, run the same code.
- “Monday” | “Friday” means → if it’s either Monday or Friday, print “Busy weekday!”.
- _ is a catch-all for all other days.
2. Nested Patterns
Sometimes data is inside other data (like structs inside enums). Pattern matching allows you go deep into these structures and pull out values.
enum Device {
Phone { brand: String, os: String },
Laptop { brand: String, year: u32 },
}
fn main() {
let gadget = Device::Phone {
brand: String::from("Samsung"),
os: String::from("Android"),
};
match gadget {
Device::Phone { brand, os } => {
println!("Phone Brand: {}, OS: {}", brand, os);
}
Device::Laptop { brand, year } => {
println!("Laptop Brand: {}, Released: {}", brand, year);
}
}
}
Output:
Phone Brand: Samsung, OS: Android
Learn More About Rust Programming
- What are Strings in Rust?
- What are Lifetimes in Rust?
- What is the Slices in Rust?
- What are the borrowing in Rust?
Exercise: Student Activity Matcher
You are building a small Rust program for a college activity system.
Each student can be:
- Study { subject, hours } → means the student is studying a subject.
- Sports { game } → means the student is playing a sport.
- Hobby(String) → means the student is doing a hobby.
Your task:
- Use pattern matching with OR (
|) to handle multiple hobbies with one action. - Use nested patterns to extract details like subject and
hours.
Rust code:
enum Activity {
Study { subject: String, hours: u32 },
Sports { game: String },
Hobby(String),
}
fn main() {
let student_activity = Activity::Study {
subject: String::from("Math"),
hours: 3,
};
match student_activity {
Activity::Study { subject, hours } if hours >= 2 => {
println!("Studying {} for {} hours - Great focus!", subject, hours);
}
Activity::Study { subject, hours } => {
println!("Studying {} for only {} hour - Try more!", subject, hours);
}
Activity::Sports { game } => {
println!("Playing {} - Stay active!", game);
}
Activity::Hobby(hobby) if hobby == "Drawing" | hobby == "Singing" => {
println!("Creative hobby detected: {}", hobby);
}
Activity::Hobby(hobby) => {
println!("Doing hobby: {}", hobby);
}
}
}
Output:
Studying Math for 3 hours - Great focus!

M.Sc. (Information Technology). I explain AI, AGI, Programming and future technologies in simple language. Founder of BoxOfLearn.com.