Day 8: Rust Match

Pattern Matching

Today I’ll be tackling a topic I’ve been looking forward to. The Rust Match construct. When I first saw match, I didn’t really understand it at all. It felt like a foreign concept that would take forever to understand, but going through it is pretty understandable.

In the Rust Book, match is introduced just after enum as a way to conditionally handle each value in the enum. I’ll follow the same approach because in JavaScript we do not support enums natively. I remember them from previous languages but it’s worth a refresher.

Enums

Enumerations are a data type that enables a variable to have a set of predefined constant values. The variable must have one of those values that have been defined for it.

Example:

You want to represent the cardinal points, North, East, West, and South in code. An enum would be a great data type for this. The code would look like below:

enum CardinalDirection {
    North,
    South,
    East,
    West
}
let direction = CardinalDirection::East;Code language: JavaScript (javascript)

In Rust, you can add additional data to enums. The example given in the book would be Ip addresses.

enum IpAddrType {
    V4,
    V6
}

Let’s say you wanted to save the IP address itself, you could use a struct but it’s more elegant to save that in the enum variable.

enum IpAddrType {
    V4(String),
    V6(String)
}Code language: JavaScript (javascript)

Here we’ve defined the options and say they accept a string. Our instance would be

let four = IpAddrType::V4(String::from("127.0.0.1"));
let six = IpAddrType::V6(String::from("::1"));Code language: JavaScript (javascript)

Now that we have a basic understanding of enum we can move on to what we are actually interested in. Match

Match

So I’m just going to start off with a statement that may be controversial.

Match is a Rust Switch statement.

Angry Rustician Mob
Ryan Howerter Get him!

Hold on, put the pitchforks down, even Rust acknowledges this… Great, now that the Rustician riots have been calmed slightly let me explain myself.

Match is a Rust Switch statement, but it’s not JUST a switch statement.

As a switch

Let’s do the normal stuff first to get a handle on the form. You can do everything you would normally use a switch for. So I can turn this JavaScript Switch into Match

switch(expression) {
  case 1:
    // do 1 stuff
    break
  case 2:
    // do 2 stuff
    break
  default:
    // default stuff
}Code language: PHP (php)

In Rust this would be

match expression {
    1 => //do 1 stuff,
    2 => //do 2 stuff,
    _ => //do default stuff
}Code language: PHP (php)

More advanced Match

Match requires that the arms, be exhaustive, You will get a compiler error if they aren’t.

Like Switch, Match supports numbers, strings and bools. Basically everything swtich can do. But on top of that Match also supports enums, ranges, structs, arrays, tupples, wildcards and placeholders. It will destructure variables if needed, so you can say

    let tupple = (2, 2, 3);
    match tupple {
        (2, _, 3) => println!("#2_3"),
        (_, _, 3) => println!("#__3"),
        _ => println!("Default"),
    }Code language: PHP (php)

Or use enums

enum IpAddrType {
    V4(String),
    V6(String),
}

let ip = IpAddrType::V4(String::from("127.0.0.1"));

match ip {
    IpAddrType::V6(ref ip_addr) => println!("match v6 {:?}", ip_addr),
    IpAddrType::V4(ref ip_addr) => println!("match v4 {:?}", ip_addr),
}Code language: PHP (php)

Essentially match has the form

match VALUE {
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
}Code language: PHP (php)

Where PATTERN is any valid Rust Pattern. On a side note this is the only time thus far I’ve seen the JavaScipt style anonymous thingy. Another example would be using ranges:

    let i = 3;
    match i {
        1..=4 => println!("5 matched"),
        5..=10 => println!("3 matched"),
        _ => println!("other matched"),
    }Code language: PHP (php)

Note on Ranges, as of the time I wrote this, exclusive range pattern and open ended range patterns were still experimental. You can use them but not on stable.

If you want to use the value being matched, you can.

    let i = 3;
    match i {
        value => println!("{} matched", value)
    }Code language: JavaScript (javascript)

Or a more complicated example:

    let i = 5;
    match i {
        value if value > 4 => println!("{} matched", value),
        value if value < 4 => println!("{} matched", value),
        _ => println!("Other"),
    }Code language: PHP (php)

As you can see the possibilities are endless, so while match is a switch, it’s a way more powerful switch.

Rust Match is a Switch on steroids.
Sarah G Rust Match is a switch on steroids.

Realising it’s a switch goes a long way in understanding how to use it, at least it did for me. So what do you think? Did I do match justice? Are you still triggered I called it a switch? Let me know on Twitter, @phoexer and as always, happy coding.