The match statement allows to evaluate an expression and run actions depending on the obtained value. The value may tested using:
A single value.
A list of choices separated by
|characters.A range.
A variable name that caches all values or the
_to catch those values but ignore them.
Example:
for i in [-50, 3, 46, 7, 10] {
match i {
0..5 => println!("Between 0 and 5 excluded."),
7 | 13 | 20 => println!("Some number in 7, 13, 20."),
10 => println!("Exactly 10!"),
_ => println!("Other value."),
};
}Other value.
Between 0 and 5 excluded.
Other value.
Some number in 7, 13, 20.
Exactly 10!
()The actions may themselves be expressions, in which case they must all return the same type. Example:
for i in [-50, 3, 46, 7, 10] {
let j = match i {
0..5 => 1,
7 | 13 | 20 => 2,
10 => 3,
_ => 10,
};
println!("{:?}", (i, j));
}(-50, 10)
(3, 1)
(46, 10)
(7, 2)
(10, 3)
()13.3.1Missing cases¶
match must be exhaustive and cover all cases, otherwise the compiler
will raise an error:
let n = 1111;
match n {
-100..100 => println!("My single case.")
};[E0004] Error: non-exhaustive patterns: `i32::MIN..=-101_i32` and `100_i32..=i32::MAX` not covered
╭─[ command_4:1:1 ]
│
2 │ match n {
│ ┬
│ ╰── patterns `i32::MIN..=-101_i32` and `100_i32..=i32::MAX` not covered
3 │ -100..100 => println!("My single case.")
│ │
│ ╰─ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms: `,
i32::MIN..=-101_i32 | 100_i32..=i32::MAX => todo!()`
───╯13.3.2Using variables¶
For each match case, we may set the matched value into a variable that we can use:
Inside an additional
ifcondition.In the action part, on the right of
=>.
For instance, if we define the following function:
fn double(n: i32) -> i32 {
2 * n
}We may test its returned values with match, and set them into a
variable n:
for i in [-50, 3, 46, 5, 7, 10] {
match double(i) {
n if n <= -10 => println!("{n} is <= -10."),
n @ 0..7 => println!("Between 0 and 7 excluded: {n}."),
n @ (7 | 13 | 20) => println!("{n} is in 7, 13, 20."),
10 => println!("Exactly 10!"),
n => println!("Other value: {n}."),
};
}-100 is <= -10.
Between 0 and 7 excluded: 6.
Other value: 92.
Exactly 10!
Other value: 14.
20 is in 7, 13, 20.
()13.3.3Handling floats¶
Float values can be used inside a match statement. One way to match
them is to use float ranges:
match 1.4 {
0.0..0.9 => println!("First case"),
0.9..1.8 => println!("Second case"),
x => println!("Unhandled value {x}"),
}Second case
()Another way is to use variables with if statements:
match 3.7 {
x if x <= 0.0 => println!("First case: {x}"),
x if x <= 0.9 => println!("Second case: {x}"),
x if x <= 3.3 => println!("Third case: {x}"),
x if x <= 7.6 => println!("Fourth case: {x}"),
x => println!("Unhandled value {x}"),
}Fourth case: 3.7
()let mass_prices = [(0.3, 3.4), (1.2, 2.7), (2.0, 2.9), (4.0, 3.2)];
mass_prices[(0.3, 3.4), (1.2, 2.7), (2.0, 2.9), (4.0, 3.2)]13.3.4With variants¶
The match statement is often used on enum values or variants. Match
cases can extract data stored inside the variants.
Here is an enum type Color that defines two variants. One for grey
levels, and another for RGB colors:
enum Color {
Grey(u8),
Rgb(u8, u8, u8),
}The following match statement extracts variants’ data in both cases:
for c in [Color::Grey(99), Color::Rgb(10, 30, 60)] {
match c {
Color::Grey(n) => println!("Grey level {n}."),
Color::Rgb(r,g,b) => println!("RGB color ({r}, {g}, {b})."),
}
}Grey level 99.
RGB color (10, 30, 60).
()