Rust Interview Questions

35 Questions
Rust

Rust

Web DevelopmentIoT

Question 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, and 3 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 and while 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.

Recent job openings