(This will need to be updated to include the things in this release, but I haven't gotten to it yet.)
if let Bar::Qux(x) = foo { ... )Assuming there's not some wider design issue, I'd probably implement an unwrap_qux() method on the Bar enum
https://play.rust-lang.org/?version=beta&mode=debug&edition=...
Not to mention how much each language differs in how the syntax and behavior is implemented, making it harder for beginners everywhere to ramp up.
Like the smart-match clusterf* in Perl, pattern matching is just too darn clever for its own good.
Rust’s pattern matching is deliberately fairly limited in what it can do; it’s all about destructuring types, not running arbitrary code like Perl’s smart-match (which even so I would not describe as a disaster). It’s conceptually very clean—arguably simpler than what ECMAScript already has. `let PATTERN = EXPRESSION;`, `if let PATTERN { … }`, `match EXPRESSION { PATTERN => … }`, `fn NAME(PATTERN: TYPE)`, &c., everything that can introduce a new binding is a pattern. Some of the uses of patterns are refutable (match branches, `if let`, `while let`), and some irrefutable (`let`, `for`, function arguments, closure arguments).
ECMAScript already has destructuring in various places, corresponding to irrefutable pattern matching; what the proposal’s `case` expression introduces is essentially just refutable destructuring, plus a smidgeon of expression-orientation (`->` corresponding to `=>`, that `case` is an expression that yields a value, rather than a statement) in a place that sorely needs it. This is a very logical extension of the language.
If TC39 or equivalent were to design a new language to actively replace JavaScript (meaning something that all extant JavaScript code should be able to migrate to easily, preferably automatedly), there is no doubt in my mind that the language would be more expression-oriented than ECMAScript is, that destructuring syntax would be brought in line with what we call pattern matching so that there was one coherent concept underneath (probably called pattern matching), and that `switch` would use it, becoming equivalent to this proposal.
The way people use JavaScript these days, these things are useful.
(I write all this as an expert and heavy user of both Rust and JavaScript; I use JavaScript more, most of the time, but prefer Rust. Rust was the first language I learned with each of algebraic data types, pattern matching and expression orientation.)
Pattern matching is a can of worms in the way people think these should work and the way compilers implement them. It holds unexpected behavior in so many ways and it's not at all about language abuse, but about giving a tool that is prone to misunderstanding and flimsy enough for programmers to shoot themselves and others in the foot. And it's not the same pattern matching in Haskell (which is fine) that it is in ES (where it's not).
Fortunately the TC39 proposal looks somewhat stalled and you can already see in the Babel plugin and proposal discussion questions on why or how this does or does not do behavior X, Y or Z or how syntax should be implemented. This is a bad sign on how pattern matching can be confusing, but then maybe this may be a sign it never gets past stage 1. Here are a few soundbites from the proposal:
when true -> ... // ok, if x === true
when undefined -> ... // not ok, this creates a local var called "undefined"
when Infinity -> ... // ok, if x === Infinity
when -Infinity -> ... // Syntax error!
when /.*/ -> ... // not ok, unsupported, surprise surprise.
when {x} = {x:1} -> ... // great, we check if x exists and set a value on it if it doesn't?!?!
when {status = 200} if (status === 200) -> ... // left as an exercise for the reader
Now I just love this one, as it just subsumes many of my concerns: const y = 2;
case (1) { // matching on a value itself, lovely
when y if (y === 2) -> 'does not match', // y is (re)created locally for the if!
when x if (x === 1) -> 'x is 1' // you're a psycho if you write code like this
}
Now, I must confess I do like matching on types as they can substitute method dispatching elegantly and should be simple to understand and implement, but this is more suited for typed languages, not ES. Same for basic parameter existence as a destructuring dispatch for arrays and objects. But never on value, ranges (`[1..=x]` - yuck, Rust!) or anything more complex.Historically, smart match in Perl was "stolen" from the ideas of Perl 6. Perl 6 (now named Raku https://raku.org using the #rakulang tag on social media) learned from the problems found in Perl, and changed its smart-matching model from symmetric to asymmetric. Basically, `a ~~ b` is syntactic sugar for `b.ACCEPTS(a)`. By transferring the responsibility for what smart matching means to an object of a given class, made it possible to make much more sane default behaviour, as well as allowing authors to define their own smart-matching behaviour for custom classes.
Part of the problem is that Perl doesn't have as strong of a type system. (Is is an int or a string, or is is both? The runtime certainly doesn't know.)
It was also symmetric in 5.10 (changed in 5.10.1), which didn't help.
---
The major mistake was not making it experimental from the start.
(The smartmatch feature is why marking things as experimental is now a thing.)
---
If it is carefully designed, it should prove to be useful just like it has in Raku.
I don't see how it can be designed well enough. The fundamental problem is that Perl operators are monomorphic and variables are polymorphic. This was the same problem for things like keys and each on references, for example.
If you actually read what I wrote, you'll note that everything I said makes it a difficult to impossible in Perl.
I meant adding the feature to Rust, which doesn't have the same difficulties.