🏁 Pattern Matching

What is it?

  • destructuring
  • access to data
  • like equality but for the shape of values
  • branching / control

How do we do it?

Let

When a type has a single constructor you can pattern match using the let keyword:


#![allow(unused)]
fn main() {
struct MyRecord {
    name: String,
    age: u8,
}

fn record_string(record: MyRecord) -> String {
    let MyRecord{ name, age } = record;
    format!("{} is {} years old", name, age)
}

let value = MyRecord {
    name: "Frodo Baggins".to_string(),
    age: 50,
};

println!("{}", record_string(value));
}

But this doesn't work when the type has more than one constructor because we can't handle all the forms that a value might take:

enum Hobbit {
    Frodo {
        has_ring: bool,
    },
    Samwise {
        has_potatoes: bool,
    },
    Other {
        name: String,
        likes: String,
    }
}

fn hobbit_string(hobbit: Hobbit) -> String {
    let Hobbit::Frodo{ has_ring } = hobbit;
    format!("Frodo Baggins {} the ring", if has_ring { "has" } else { "doesn't have" })
}

fn main() {
    println!("{}", hobbit_string(Hobbit::Samwise{ has_potatoes: true }));
}

Using the match keyword:

enum Hobbit {
    Frodo {
        has_ring: bool,
    },
    Samwise {
        has_potatoes: bool,
    },
    Other {
        name: String,
        likes: String,
    }
}

fn hobbit_string(hobbit: Hobbit) -> String {
    match hobbit {
        Hobbit::Frodo{ has_ring } => format!(
            "Frodo Baggins {} the ring",
            if has_ring {
                "has"
            } else {
                "doesn't have"
            }
        ),
        Hobbit::Samwise{ has_potatoes } => format!(
            "Samwise Gamgee ... potatoes? {}",
            if has_potatoes {
                "mix em, mash em, throw em in a stew"
            } else {
                "no thanks"
            }
        ),
        Hobbit::Other{ name, likes } => format!("{} likes {}", name, likes),
    }
}

fn main() {
    println!("{}", hobbit_string(Hobbit::Samwise{ has_potatoes: true}));
}