This Is What I Know about match
December 16, 2021
I've been learning Rust for some time now, and really enjoying it - the static typing, the helpful compiler, the tooling, the documentation, just about everything. I think I'm in the neophyte stage. Anyway, this is my attempt to describe the match keyword, mostly (but certainly not entirely) in my own words.
match is the keyword for pattern matching - like case in Bash and other languages, though a little more powerful. Like case, it is similar to a series of if/else expressions, where you go down through them to control the flow of code. However, if and else if expressions must evaluate to a boolean value. The match expression can evaluate to any type. Each possibility is an "arm" that has a pattern that is evaluated. All arms need to return something of the same type. The first pattern that is true has the code associated with it run (which follows a => symbol, potentially in a curly brace block, if longer than one line) - Rust will not examine any subsequent arms. Additionally, matches are exhaustive: every possible option must be handled, otherwise the code will not compile.
Use "match guards" to further refine what you are matching. This is done by following the pattern with a bool-type expression. See 2nd arm of the longer example below.
Here are some syntax options for the tests (the left side):
- just provide the value
x ..= y- inclusive range from x to yx | y- x or y_- any (this will often be done as the last arm to catch all other possibilities)
Here is an example from the Rust book, matching on enum variants:
This example (from my solution on Exercism) shows a number of these concepts as well as the matches! macro:
You can also assign the result from a match expression to a variable (example from Tim McNamara's Rust in Action, Ch. 2):
let needle = 42;
let haystack = ;
for item in &haystack
There is a shorthand expression when you care about only one of the cases and don't need to do anything for all others: if let:
if let Some = some_u8_value
(An update from the future: At first, I found the let here to be confusing, because nothing was being assigned in the block. What is the let doing!? It seems clearer syntax would be if some_u8_value == Some(3). I'm sure there are good reasons this isn't possible. But after a while, it became second nature so I stopped thinking about it.)
You can also use else with this, when you want to define the behavior to be done instead of just no behavior.
Sources:
- https://doc.rust-lang.org/std/macro.matches.html
- https://doc.rust-lang.org/std/keyword.match.html
- https://doc.rust-lang.org/reference/expressions/match-expr.html
- https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards
- https://doc.rust-lang.org/stable/book/ch06-00-enums.html
- https://www.rustinaction.com/