Irrefutable Patterns

In day 1 we briefly saw how patterns can be used to destructure compound values. Let’s review that and talk about a few other things patterns can express:

fn takes_tuple(tuple: (char, i32, bool)) {
    let a = tuple.0;
    let b = tuple.1;
    let c = tuple.2;

    // This does the same thing as above.
    let (a, b, c) = tuple;

    // Ignore the first element, only bind the second and third.
    let (_, b, c) = tuple;

    // Ignore everything but the last element.
    let (.., c) = tuple;
}

fn main() {
    takes_tuple(('a', 777, true));
}
This slide should take about 5 minutes.
  • All of the demonstrated patterns are irrefutable, meaning that they will always match the value on the right hand side.

  • Patterns are type-specific, including irrefutable patterns. Try adding or removing an element to the tuple and look at the resulting compiler errors.

  • Variable names are patterns that always match and which bind the matched value into a new variable with that name.

  • _ is a pattern that always matches any value, discarding the matched value.

  • .. allows you to ignore multiple values at once.

More to Explore

  • You can also demonstrate more advanced usages of .., such as ignoring the middle elements of a tuple.

    #![allow(unused)]
    fn main() {
    fn takes_tuple(tuple: (char, i32, bool, u8)) {
        let (first, .., last) = tuple;
    }
    }
  • All of these patterns work with arrays as well:

    #![allow(unused)]
    fn main() {
    fn takes_array(array: [u8; 5]) {
        let [first, .., last] = array;
    }
    }