fn main() {
let x = |_| Some(1);
let (|x| x) = match x(..) {
|_| Some(2) => |_| Some(3),
|_| _ => unreachable!(),
};
assert!(matches!(x(..), |_| Some(4)));
}
This example is just compiled. Take a first glance at this example, you might be surprised why the closure can be a pattern.
The magic is |x| x, |_| Some(2), |_| _ , and |_| Some(4) is not a closure. They are patterns. So, why is the prefix | permitted in a pattern? Is |a|b syntactically equivalent to a | b? If it is, where is the rule?
Reading through the RFC, it's mostly intended to alleviate the fencepost problem for macros: Without this, either the first or last item in the alternation has to be special-cased.
Secondarily, other languages (notably F#) allow this syntax in their match expressions and some programmers with that background use it habitually to improve their code's formatting.
I didn't say the closure is a pattern. I said that increasing the pattern that has the prefix | could bring confusion for users since they look the same.
That's a matter of personal preference. But note that trailing | is not allowed in patterns, so you can't easily interchange the lines with patterns, and the last pattern in a sequence won't have either leading or trailing |. Personally I prefer the leading |, because it immediately separates single-pattern cases from multi-pattern ones.
So, I ask why we try to introduce the syntax into the current edition. It appears to me that it can easily produce ambiguity between the pattern and the closure.
Sure, but only when someone is actively trying to be malicious and you're not reading warnings and you're not using rustfmt. Rust doesn't prevent bad code.
There's a bunch of pattern cases that are imperfect without the warnings. match foo.cmp(&bar) { Less => … } is a classic, for example. But that's why warnings exist.
Current edition? It was stabilized in 1.25 (before editions / Edition 2015), like @azriel91 said.
If you read the related issues, it certainly wasn't universally popular, and the OP demonstrates some confusing-to-humans constructions. But there's no parsing ambiguity; no pattern can start with |, and the leading | is just swallowed, as far as I see. Closures aren't patterns, like @H2CO3 said.
You can create obfuscated or confusing code in all sort of other ways too. Even code that looks normal! I don't know that I've used a language where that isn't the case.
error: a trailing `|` is not allowed in an or-pattern
--> src/main.rs:3:13
|
3 | | _ | => {}
| - ^ help: remove the `|`
| |
| while parsing this or-pattern starting here