🎓 A1Learner
🔍
0 of 142 lessons completed

Rust Pattern Places

A pattern is a shape that tests a value and binds names to its pieces. Patterns appear in more places than match arms.

Every let holds a pattern

Every let has the shape let PATTERN = value. A plain name like plain is the simplest pattern. It binds everything. A tuple pattern must have the same number of pieces as the tuple:

let plain = 5;
let (x, y) = (1, 2);
println!("plain = {} x = {} y = {}", plain, x, y);
// let (a, b) = (1, 2, 3); // error E0308: two names cannot split three values

The value after for is a pattern

for (index, value) pulls each pair apart as the loop runs:

let words = vec!["one", "two"];
for (i, w) in words.iter().enumerate() {
    println!("{} = {}", i, w);
}

Function inputs are patterns

Function parameters are patterns too: the borrowed tuple is pulled apart before the body starts:

fn show(&(x, y): &(i32, i32)) {
    println!("({}, {})", x, y);
}
show(&(3, 5));

Closure inputs work the same way

Closure parameters work the same way, because a closure is like a small function:

let add_pair = |(a, b): (i32, i32)| a + b;
println!("sum = {}", add_pair((3, 4)));

A chain can mix forms

Use if let for one value. Use a plain else if test next. Then use else if let for another. The tests do not have to relate to each other:

let a: Option<i32> = Some(5);
let b: Option<i32> = None;
if let Some(x) = a {
    println!("a has {}", x);
} else if b.is_none() {
    println!("b is empty");
} else if let Some(y) = b {
    println!("b has {}", y);
}

A pattern can shadow a name

A pattern inside if let shadows an outer name of the same spelling. Inside the block, age is the new, unwrapped one:

let age: Result<i32, &str> = Ok(21);
if let Ok(age) = age {
    println!("inside, age = {}", age);
}

Example

fn print_point(&(x, y): &(i32, i32)) {
    println!("point is ({}, {})", x, y);
}
fn main() {
    let (name, score) = ("Ada", 42);
    println!("{} scored {}", name, score);
    print_point(&(3, 5));
    let pairs = vec![(1, "one"), (2, "two")];
    for (n, word) in pairs {
        println!("{} = {}", n, word);
    }
}

In this example, three pattern places appear. The let line matches the tuple ("Ada", 42) against the pattern (name, score). So name is "Ada" and score is 42. print_point takes &(x, y) as its parameter pattern. The borrowed tuple (3, 5) is pulled apart on the way in. So the body can print x and y directly. The for loop uses the pattern (n, word) on each pair in the Vec, printing 1 = one and 2 = two. No match appears anywhere — the patterns did the work alone.

Note

That new name only exists inside the block.

An extra test on that name cannot join the if let line.

Write the test inside the block instead.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

In fn print_point(&(x, y): &(i32, i32)), what is &(x, y)?