How to use Pattern Matching in Rust

Reading Time: 3 minutes

Rust has an extremely powerful control flow operator called Match. Pattern matching in Rust works by checking if a place in memory matches a certain pattern. Patterns can be :

  • literal values
  • variable names
  • wildcards, and many other things

Destructuring using Pattern Matching

Pattern matching can use to destruct following items :

  • Structures
  • Enums
  • Tuples

 Destructuring breaks up a value into its component pieces. The syntax used is almost the same as when creating such values.

Destructing Structures

A struct, or structure, is a user-defined data type that lets you create a data type that can be used to group items of possibly different types into a single entity. 

Syntax :

struct STRUCTURENAME {
   field1:data_type,
   field2:data_type,
   field3:data_type
}

The struct keyword is used to declare a structure. Since structures are statically typed, every field in the structure must be associated with a data type.

Example :

fn main() {
    struct Foo {
        x_values: (u32, u32),
        y_values: u32,
    }

let foo = Foo { x_values: (1, 2), y_values: 3 };

match foo {
        Foo { x_values: (1, b), y_values } => println!("First of x is 1, b = {},  y = {} ", b, y),
        Foo { y_values: 2, x_values: i } => println!("y is 2, i = {:?}", i),
       }
}
        

Output :

Destructing Enums

Enums are types which have a few definite values. Each variant in the enums can optionally have data associated with it. We use enums when we have to select a value from a list of possible variants.

Syntax :

enum ENUMNAME {
   variant1,
   variant2,
   variant3
}

The syntax for defining variants resembles the syntax used to define structs. A value of the enum can match any of the variants.

Example :

enum DIRECTIONS {
        Up,
        Down,
        Left,
        Right
    }

fn main() {
    let direction = DIRECTIONS::Right;
    match direction {
       DIRECTIONS::Up => println!("Direction selected is UP"),
       DIRECTIONS::Down => println!("Direction selected is DOWN"),
       DIRECTIONS::Left => println!("Direction selected is LEFT"),
       DIRECTIONS::Right => println!("Direction selected is RIGHT")
    }
}

Output :

Destructing Tuples

Tuple is a compound data type. A scalar type can store only one type of data. In compound types, we can store more than one value at a time and it can be of different types.

Syntax :

let tuple_name:(data_type1,data_type2,data_type3) = (value1,value2,value3);

OR

let tuple_name = (value1,value2,value3);

Example :

fn main() {
    let values = (1,2.5,"Name");
    match values {
       (0, 2_value, 3_value) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),
        (1, ..)  => println!("First is `1` and the rest doesn't matter"),
        _      => println!("It doesn't matter what they are"),
    }
}

Output :

Refutability: Whether a Pattern Might Fail to Match

A pattern is said to be refutable when it has the possibility of not being matched by the value it is being matched against. Patterns that will match for any possible value passed are irrefutable.

Example :

Refutable

Example :

fn main() {
    let some_option_value: Option<i32> = None;
    let Some(value) = some_option_value;
}

Output :

some_option_value was a None value, it would fail to match the pattern Some(value), meaning the pattern is refutable.

Irrefutable

Example :

fn main() {
    let some_option_value: Option<i32> = None;
    match some_option_value{
        Some(value) => print!("Irrefutable pattern value is {}",value),
        None => print!("Irrefutable pattern value is None")
    }
}

Output :

some_option_value was a None value, it matches with None arm, meaning the pattern is irrefutable.

Thanks for reading !!

If you want to read more content like this?  Subscribe to Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe to Rust Times Newsletter: https://bit.ly/2Vdlld7.


Knoldus-blog-footer-image

Leave a Reply