As tuple matching with ranges works, I hoped something similar would also work with alternatives:
match x {
(1, 1) => println!("A"),
(1, 2 ... 3) => println!("B"), // ranges work
(2 | 5, 4 | 6) => println!("C"), // this doesn't
_ => println!("D")
}
Is there an elegant solution to this or does one have to either "unroll" the alternatives or resort to chained if
/else if
instead of pattern matching?
Alternatives are not part of the syntax for patterns; a | b
is not a pattern. Alternatives can only be used to combine patterns in a match
arm (they are not available in if let
and while let
expressions either).
A workaround is to use guards:
match x {
(1, 1) => println!("A"),
(1, 2 ... 3) => println!("B"),
(a, b) if (a == 2 || a == 5) &&
(b == 4 || b == 6) => println!("C"),
_ => println!("D")
}
Guards are arbitrary expressions (that must evaluate to a bool
), so they can call functions.
match x {
(1, 1) => println!("A"),
(1, 2 ... 3) => println!("B"),
(a, b) if [2, 5].contains(&a) &&
[4, 6].contains(&b) => println!("C"),
_ => println!("D")
}
Since Rust 1.53, pattern matching was extended to allow nested |
patterns. So the original presented example compiles as is in that regard (Playground link):
match x {
(1, 1) => println!("A"),
(1, 2..=3) => println!("B"),
(2 | 5, 4 | 6) => println!("C"),
_ => println!("D")
}
(...
for inclusive ranges were deprecated in 2021 Edition in favor of ..=
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With