Skip to content

Instantly share code, notes, and snippets.

@max-itzpapalotl
Last active February 25, 2024 14:46
Show Gist options
  • Save max-itzpapalotl/a12f9b827812d862a1920e085ea8a51a to your computer and use it in GitHub Desktop.
Save max-itzpapalotl/a12f9b827812d862a1920e085ea8a51a to your computer and use it in GitHub Desktop.
20. Matching

20. Matching

In this video I give an overview over the matching capabilities in Rust.

Types of patterns

#[derive(Debug)]
enum X {
    A,
    B(i64),
    C(String),
}

#[derive(Debug)]
struct S {
    pub name : String,
    pub age : u16,
}

fn main() {
    let args : Vec<String> = std::env::args().collect();

    // match expression on literals or with a variable:
    let x : X = match args.len() {
        2     => X::C(args[1].clone()),
        0 | 1 => X::A,
        l     => X::B(l as i64),
    };
    println!("{x:?}");

    // match statement to destruct enum:
    match x {
        X::A => {
            println!("Empty A");
        },
        X::B(n) => {
            println!("Multiple arguments: {}", n);
        },
        X::C(s) => {
            println!("Exactly one argument: {}", s);
        },
    };

    // matching to destruct tuple:
    let t : (i64, String) = (17, "abc".to_string());
    match &t {
        (i, s) => {
            println!("A number {i} and a string {s}.");
        },
    };
    // Or:
    let (i,s) = t;   // matching in `let` statements
    println!("i={i} s={s}");

    // matching to destruct an array:
    let a : [u64; 3] = [2, 3, 5];
    let [x, y, z] = a;
    println!("x={x} y={y} z={z}");

    // matching to destruct a struct:
    let s = S{name:"Karl".to_string(), age: 55};
    let S{name: n, age: a} = &s;
    println!("name={n} age={a}");
}

Places to match

#[derive(Debug)]
enum X {
    A,
    B(i64),
    C(String),
}

#[derive(Debug)]
struct S {
    pub name : String,
    pub age : u16,
}

fn f(S{name: _, age: a} : &S) -> u16 {
    println!("f called with age {a}");
    a+1
}

fn main() {
    let args : Vec<String> = std::env::args().collect();

    // match expression on literals or with a variable:
    let x : X = match args.len() {
        2     => X::C(args[1].clone()),
        0 | 1 => X::A,
        l     => X::B(l as i64),
    };
    println!("{x:?}");

    // if let:
    if let X::C(s) = x {
        println!("String case: {s}");
    }

    // while let:
    let mut stack = Vec::new();
    stack.push("A1");
    stack.push("B2");
    stack.push("C3");
    while let Some(top) = stack.pop() {
        println!("{}", top);
    }

    // for loops:
    let v = vec!["aaa", "bbb", "ccc"];
    for (index, value) in v.iter().enumerate() {
        println!("{} is at index {}", value, index);
    }

    // let statements:
    let s = S{name: "Max".to_string(), age: 54};
    let S{name:m, age:_} = s;
    println!("Name: {m}");
    let i = 1;
    let j = 2;
    let (j, i) = (i, j);
    println!("i={i} j={j}");

    // function arguments:
    let s = S{name: "Max".to_string(), age: 54};
    println!("One more: {}", f(&s));
}

Refutability

A pattern can be "refutable" or "irrefutable". An irrefutable pattern matches always, given an object of a certain type. A refutable pattern can be rejected. In certain contexts only irrefutable patterns are allowed (function arguments, let statements, etc.), in other contexts refutable patterns are allowed and can then control the flow of execution (match expressions, if let statements, while let statements, etc.).

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment