Refutable patterns
Refutable patterns don't only provide variable names to bind data to, but also constraints to match against. They can be used as guard into a code block (then called arm) and bound variables are only available inside that block, living in its scope. There is a catch, however: The constraints have to be static, since the equivalent code is generated at compile time. Also, using variable identifiers in pattern constraints would make it extremely easy to confuse with variable binding.
Matching against refutable patterns is extremely flexible otherwise.
You can match refutable patterns either by using if let
for one arm, with an optional else
if the constraint isn't fulfilled (no variables will be bound in this case), or a match
statement for checking multiple arms.
You can also combine multiple patterns to check the same arm for each, though only variable names present in every of those patterns will be bound. If you want to bind a value to a variable while also using a constraint on it, you can do so using the @
symbol.
That was all very dry, wasn't it? Let's see how these patterns look in some example code.
struct Person { pub name: &'static str, pub age: usize, } fn example() { let henry = Person { name: "Henry", age: 42 }; if let Person { name, age: age @ 20..=67 } = henry { println!("{} is probably a working adult at age {}.", name, age); } else { println!("The person is most likely not a working adult."); } } fn example2() { let point = (42, 69); match point { (0, 0) => { println!("The point is on the origin of the coordinate system.") } (x, y @ 0) | (x @ 0, y) => { println!("The point is on one of the axes at [{}, {}].", x, y); } // irrefutable pattern as default case (x, y) => { println!("The point is at [{}, {}]", x, y); } } } fn main() { example(); example2(); }
You may be able to imagine the amount of possibilities on how to structure your control flow with refutable patterns. However, some instances can still look a little weird, especially when looking back at the example code just now. Although some examples with "normal" patterns can already look concise, like the coordinate example, the real power of pattern matching only becomes apparent when combined with enums.