Rust Interview Questions
Rust
Web DevelopmentIoTQuestion 29
How does Rust's pattern matching work?
Answer:
Rust's pattern matching is a powerful feature that allows you to match against complex data structures, deconstruct values, and handle different cases in a concise and expressive way. Pattern matching in Rust is primarily done using the match
expression, but it can also be used in other contexts like if let
, while let
, and function parameters.
match
Expression
The match
expression in Rust allows you to compare a value against a series of patterns and execute code based on which pattern matches. Each pattern is followed by an arrow (=>
) and the code to execute.
Basic Example
fn main() {
let number = 7;
match number {
1 => println!("One"),
2 => println!("Two"),
3 => println!("Three"),
4 | 5 | 6 => println!("Four, five, or six"),
7..=10 => println!("Between seven and ten"),
_ => println!("Other"),
}
}
In this example:
1
,2
, and3
are matched explicitly.4 | 5 | 6
matches any of these three values.7..=10
matches any value in the range from 7 to 10 inclusive._
is a wildcard pattern that matches any value not previously matched.
Destructuring
Pattern matching can destructure complex data structures like tuples, enums, and structs to access their components.
Destructuring Tuples
fn main() {
let pair = (0, -2);
match pair {
(0, y) => println!("First is 0 and y is {}", y),
(x, 0) => println!("x is {} and second is 0", x),
_ => println!("It doesn't matter what they are"),
}
}
Destructuring Enums
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let msg = Message::Move { x: 10, y: 20 };
match msg {
Message::Quit => println!("The Quit variant has no data to destructure."),
Message::Move { x, y } => println!("Move to ({}, {})", x, y),
Message::Write(text) => println!("Text message: {}", text),
Message::ChangeColor(r, g, b) => println!("Change color to red {}, green {}, blue {}", r, g, b),
}
}
Destructuring Structs
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 0, y: 7 };
match p {
Point { x: 0, y } => println!("On the y axis at {}", y),
Point { x, y: 0 } => println!("On the x axis at {}", x),
Point { x, y } => println!("On neither axis: ({}, {})", x, y),
}
}
Conditional Matching with if let
and while let
if let
if let
allows for matching against a pattern with a single case, providing a more concise way to handle specific matches.
fn main() {
let favorite_color: Option<&str> = Some("blue");
if let Some(color) = favorite_color {
println!("Your favorite color is {}", color);
} else {
println!("You don't have a favorite color");
}
}
while let
while let
continues to run as long as a pattern continues to match.
fn main() {
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
println!("{}", top);
}
}
Advanced Patterns
Matching with Guards
Pattern guards allow for additional conditions on a match arm.
fn main() {
let num = Some(4);
match num {
Some(x) if x < 5 => println!("Less than five: {}", x),
Some(x) => println!("{}", x),
None => (),
}
}
Nested Patterns
Patterns can be nested to handle complex data structures.
enum Message {
Hello { id: i32 },
}
fn main() {
let msg = Message::Hello { id: 5 };
match msg {
Message::Hello { id: id_variable @ 3..=7 } => {
println!("Found an id in range: {}", id_variable)
}
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
Message::Hello { id } => {
println!("Found some other id: {}", id)
}
}
}
Summary
match
Expression: A powerful control flow construct that allows matching on multiple patterns.- Destructuring: Extracts values from tuples, enums, and structs.
if let
andwhile let
: Simplifies matching for single patterns and continuous matching.- Pattern Guards: Adds additional conditions to patterns.
- Nested Patterns: Handles complex data structures with nested patterns.
Rust's pattern matching is a versatile feature that enables concise and expressive code, allowing you to handle various data structures and conditions elegantly.