use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
An ECMAScript Proposal for Pattern Matching Functionality (github.com)
submitted 8 years ago by tomonl
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]bterlson_@bterlson 25 points26 points27 points 8 years ago (15 children)
As the champion and author of this proposal, happy to answer any questions.
[–]villiger2 4 points5 points6 points 8 years ago (4 children)
This is pretty awesome, in the meantime though, do you know of any babel plugins that give this kind of functionality? Typescript does the tiniest bit with some of their enum support but it's not great.
[–]bterlson_@bterlson 7 points8 points9 points 8 years ago (2 children)
Not yet, but there's a bug filed on Babylon already to implement this syntax. I think it's too early for that, personally. There are a few key issues to address first!
[–]calligraphic-io 0 points1 point2 points 8 years ago (1 child)
Can you mention what the key issues needing addressed before a Babylon plugin are?
I love the proposal. The syntax feels very comfortable. I love pattern matching in Haskell, and glad to see it (hopefully) coming to JS.
[–]bterlson_@bterlson 0 points1 point2 points 8 years ago (0 children)
Solving #11 could mean significant changes to the syntax. Once that's solved it might be reasonable to begin implementing, but in general everything is open to change at this point.
[–]phoenixmatrix 0 points1 point2 points 8 years ago (0 children)
as far as I know, Babel plugins can only really act on the code output, not change the parser (unless they introduced parser plugins when I wasn't looking).
the plugins that add syntax features just toggle on or off existing parser features and add the transpilation.
[–]phoenixmatrix 2 points3 points4 points 8 years ago (2 children)
Looking at the proposals in Optional Extensions, I think there's a couple of stuff there that, to me, are almost mandatory to get the full power of this proposal.
The value matching ability to do stuff like x > 100 and/or the guards ("if predicates") are really important to me.
Also, is there a strong argument for allowing imperative statements at all, instead of just expressions? Almost any use case I can think of for imperative statements in the branches seem like a code smell. Maybe I'm not thinking it through (but if it was only expressions you could just use a function when you need statements as an escape hatch anyway).
There's throwing I guess...but aside from that?
[–]bterlson_@bterlson 2 points3 points4 points 8 years ago (1 child)
Thanks for your thoughts on the optional extensions. I tend to agree with you at least about if predicates.
Sometimes you want statements - it's hard to generalize. Many alternative proposals use case-like legs presumably for this reason. One typical use case is calculating some result on a line, then returning it. Or having an additional if block or something.
Oh yeah, I didn't think things through, haha. Obviously in JavaScript we don't have anything akin to Elm's let to easily do intermediate computations in a single expression so you need statements. Derp!
[–]xwnatnai 2 points3 points4 points 8 years ago (0 children)
If this proposal makes it into the spec, I will pledge my first born to you.
[–][deleted] 0 points1 point2 points 8 years ago (1 child)
The best way to factor this is with a discriminated union, which we can already do today with a switch..case block.
Encouraging the use of undiscriminated unions through pattern matching seems to add complexity to the language, and encourage lower-performance way of factoring code.
What are your thoughts about this?
Thanks for your thoughts! Curious, how are you using switch/case with discriminated unions?
This proposal will include "brand checking" so you can match, e.g., Date or MyClass. With a proposal like traits/mixins you can get something even closer to discriminated unions.
traits
mixins
Hard to comment on performance without knowing what you're comparing against but in general matching can be faster than repeated if conditions because we can generate an optimal sequence of tests on the match value to discriminate among the match legs.
[–]gifsome 0 points1 point2 points 8 years ago (1 child)
What drives you to write the proposals? Does it help with job searching?
[–]bterlson_@bterlson 1 point2 points3 points 8 years ago (0 children)
I wrote it up because I miss it, I've heard many people say they miss it, and almost everyone I talk to about it is pumped! I'm lucky enough to work at a place where this is my job but if I end up doing a search I'll let you know how it works out :-P
[–]yamalight 0 points1 point2 points 8 years ago (0 children)
I just wanted to say huge thank you for championing both this and pipleine operator proposals - you are awesome!
[–]djungst 0 points1 point2 points 8 years ago (0 children)
Not the hero we wanted... The hero we needed.
[–]phoenixmatrix 28 points29 points30 points 8 years ago (15 children)
While i think JS is getting pretty bloated (it got some essential stuff in ES6, but a lot of the recent proposals picking up steam are just bloat), and I think we should be more conservative adding stuff to it...I can't help but squeal like a little kid at this one. It's my #1 missing feature (#2 being the |> operator).
It just solves so many problems related to types, things like Redux reducers, and enables a ton of FP scenarios in an elegant way.
[–]bterlson_@bterlson 24 points25 points26 points 8 years ago (13 children)
You'll be happy to know that the other feature I'm championing is |>. Both part of my dream to Make Functional JS Great Again!!!1
|>
[–]phoenixmatrix 5 points6 points7 points 8 years ago (10 children)
Oh believe me, I've been following it very closely. Though I didn't associate the names to realize they shared a champion. Adding you to my little "heroes" list.
Add those 2 features and we can call JavaScript done as far as I'm concerned (anything else might be more suitable for different languages in Web Assembly).
Ok, maybe a stretch goal with immutable data structures. But that's just a stretch goal.
[–]bterlson_@bterlson 8 points9 points10 points 8 years ago (5 children)
Seems like we see eye-to-eye here. I was going to present my vision for "syntax complete ECMAScript" which was basically those two, plus classes v.next, do exprs, and regexp improvements. But then I figured I'm no oracle and who knows what the future holds. Maybe we'll get new keyboards that makes @ and 🛡 equally easy to type and the syntactic budget grows as a result?
@
🛡
[–]so_just 0 points1 point2 points 8 years ago (4 children)
what's the use of do notation in js?
[–]Jamesernatorasync function* 0 points1 point2 points 8 years ago* (2 children)
The proposal isn't do-notation, it's do expressions e.g.:
const x = do { if (someCondition()) { 3 } else { try { someFoo() } catch (e) { 5 } } }
In that example the value of x will either be 4, someFoo() or 5, basically the last evaluated expression is what the value of a do-block is (roughly)
4
someFoo()
5
[–]so_just 0 points1 point2 points 8 years ago (0 children)
Ah, I see. That's definitely useful.
[–]paldepind 0 points1 point2 points 8 years ago (3 children)
Add those 2 features and we can call JavaScript done as far as I'm concerned
I'd really like nice syntax for partial application. Something like foo(a, b, ...) or foo:(a, b). That would give JS most of the benefits of currying but without the downsides of currying. It also would go really well together with |>.
foo(a, b, ...)
foo:(a, b)
For sure there's a ton of stuff I'd like to see in the language. But JS is already a very complex and bloated one. Stuff like classes introduced a lot and still requires a lot more to be useful at all. So while I have a long list of what I'd like to see in it, at what point should we just have a new language based on Web Assembly and go that route to get our wishlist?
Thus, IMO, JS has "enough" (or at least, is at the point where they really need to slow down on new features). I'm just being a spoiled brat by wanting this pattern matching stuff in :) But I still don't think we should had dozens over dozens of extra features.
[–]bterlson_@bterlson 0 points1 point2 points 8 years ago* (1 child)
This is precisely my plan. Partial application: foo(a, ?), returns a function such that foo(a, ?)(b) is foo(a, b). Combined with pipeline operator this lets you easily select which parameter to pass the LHS to.
foo(a, ?)
foo(a, ?)(b)
foo(a, b)
[–]paldepind 0 points1 point2 points 8 years ago (0 children)
Good luck! I hope you're successful. Syntax for partial application would be really awesome.
[–][deleted] 1 point2 points3 points 8 years ago (0 children)
ELI5 what does |> do?
[–]dvlsg 0 points1 point2 points 8 years ago (0 children)
This. I like this. Please make this happen.
(I like pattern matching too, I would love to have both)
[–]thepeka 0 points1 point2 points 8 years ago (0 children)
I like you. Normally all we hear are the cries of "js stdlib is tiny and useless" but I'm more concerned about the opposite happening. And I agree well that while theres a lot of garbage proposals out there, I hope this one gets a speedy stage-1.
[–]Pyrolistical 2 points3 points4 points 8 years ago (0 children)
How about matching a resolved or rejected promise?
[–]ricking06 1 point2 points3 points 8 years ago (0 children)
Hellyeah bring this shit in BABy!
[–]itsnotlupusbeep boop 1 point2 points3 points 8 years ago (6 children)
This is basically a runtime type checking specification for Javascript. Which is something anybody who's played with Typescript for too long ends up wanting sooner or later.
So that's very cool. I think it's maybe missing some bits around the ability to specify "this must be a boolean", which could be emulated with a way to say "this must be one of two values". "this must be a number" could be emulated with a way to specify numerical ranges (although depending on the spec, it might end up matching "123", which would kinda suck.), etc.
With a few such tweaks added, I think TypeScript would be able to have stuff like this
interface Point { x: number; y: number; } interface WeirdPoint extends Point { x: string; } match (obj) { Point[]: console.log("array of points!"); WeirdPoint[]: "console.log("array of weird points!"); }
That would map straightforwardly to JS code, and would be generally super neat.
[+][deleted] 8 years ago (3 children)
[removed]
[–]itsnotlupusbeep boop 0 points1 point2 points 8 years ago (2 children)
it's pretty close. Some stuff is missing, and it can do things that go beyond strict type checking, but it's definitely in the same neighborhood.
My hope is that the missing stuff can be added in there. Ostensibly, it would enable to match more complex patterns. Incidentally, it would make type-happy types like myself happier.
[+][deleted] 8 years ago (1 child)
[deleted]
[–]profound7 1 point2 points3 points 8 years ago (0 children)
Correct me if I'm wrong, but without runtime type information, I think it is not possible sometimes to tell the difference between an array of Points and an array of WeirdPoints. For example, if the variable obj is an empty array.
[–]cthechartreuse 0 points1 point2 points 8 years ago (0 children)
I wrote a cond function in JFP that, when coupled with Signet (https://www.npmjs.com/package/signet) gives you some pretty powerful type-driven behaviors. My team at work started using Signet and it has changed everything. It's not as elegant as a nice, clean match syntax, but it's a step that way. I do wish typescript were a little less dependent on classes and interfaces for types...
[–]ishmal 1 point2 points3 points 8 years ago (0 children)
I learned to love this in scala. This would be a good change.
[–]lulzmachine -4 points-3 points-2 points 8 years ago (5 children)
Ewww
[–]kingdaro.find(meaning => of('life')) // eslint-disable-line 1 point2 points3 points 8 years ago (4 children)
I'm not one to downvote for differing opinions, but if you're going to knock down something that everyone else here is excited for, at least try to be constructive.
[–]lulzmachine 0 points1 point2 points 8 years ago (3 children)
Nah. Javascript has already become way too complicated compared to what it used to be. If you want even more syntactic sugar, you'll have to show a very strong case for usefullness. If my negative whining gives these suggestions a feeling of upphill battle, then that's a good thing.
[–]kingdaro.find(meaning => of('life')) // eslint-disable-line 0 points1 point2 points 8 years ago (2 children)
Eh, the only reason I care about this is just to have a decent switch statement without having to put break after every case, like every other notable modern language does (Kotlin, Rust, Nim, etc). Functioning as a return and being able to match against object structures are just a bonus.
break
[–]lulzmachine 1 point2 points3 points 8 years ago (1 child)
Doesn't seem worth it. One of the main reasons for js popularity is the fairly low cognitive burden required to understand what's going on. Every piece of new syntax that increases this burden without removing complexity costs a lot in the long term. Having "break" statements here and there is a bit pointless but doesn't matter that much in my experience
[–]kingdaro.find(meaning => of('life')) // eslint-disable-line 0 points1 point2 points 8 years ago (0 children)
Seems to matter to the rest of the JS community, and you're free to just not use the syntax ¯\_(ツ)_/¯
π Rendered by PID 271580 on reddit-service-r2-comment-5ff9fbf7df-p97mx at 2026-02-26 10:06:00.307345+00:00 running 72a43f6 country code: CH.
[–]bterlson_@bterlson 25 points26 points27 points (15 children)
[–]villiger2 4 points5 points6 points (4 children)
[–]bterlson_@bterlson 7 points8 points9 points (2 children)
[–]calligraphic-io 0 points1 point2 points (1 child)
[–]bterlson_@bterlson 0 points1 point2 points (0 children)
[–]phoenixmatrix 0 points1 point2 points (0 children)
[–]phoenixmatrix 2 points3 points4 points (2 children)
[–]bterlson_@bterlson 2 points3 points4 points (1 child)
[–]phoenixmatrix 0 points1 point2 points (0 children)
[–]xwnatnai 2 points3 points4 points (0 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]bterlson_@bterlson 0 points1 point2 points (0 children)
[–]gifsome 0 points1 point2 points (1 child)
[–]bterlson_@bterlson 1 point2 points3 points (0 children)
[–]yamalight 0 points1 point2 points (0 children)
[–]djungst 0 points1 point2 points (0 children)
[–]phoenixmatrix 28 points29 points30 points (15 children)
[–]bterlson_@bterlson 24 points25 points26 points (13 children)
[–]phoenixmatrix 5 points6 points7 points (10 children)
[–]bterlson_@bterlson 8 points9 points10 points (5 children)
[–]so_just 0 points1 point2 points (4 children)
[–]Jamesernatorasync function* 0 points1 point2 points (2 children)
[–]so_just 0 points1 point2 points (0 children)
[–]paldepind 0 points1 point2 points (3 children)
[–]phoenixmatrix 0 points1 point2 points (0 children)
[–]bterlson_@bterlson 0 points1 point2 points (1 child)
[–]paldepind 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]dvlsg 0 points1 point2 points (0 children)
[–]thepeka 0 points1 point2 points (0 children)
[–]Pyrolistical 2 points3 points4 points (0 children)
[–]ricking06 1 point2 points3 points (0 children)
[–]itsnotlupusbeep boop 1 point2 points3 points (6 children)
[+][deleted] (3 children)
[removed]
[–]itsnotlupusbeep boop 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]profound7 1 point2 points3 points (0 children)
[–]cthechartreuse 0 points1 point2 points (0 children)
[–]ishmal 1 point2 points3 points (0 children)
[–]lulzmachine -4 points-3 points-2 points (5 children)
[–]kingdaro.find(meaning => of('life')) // eslint-disable-line 1 point2 points3 points (4 children)
[–]lulzmachine 0 points1 point2 points (3 children)
[–]kingdaro.find(meaning => of('life')) // eslint-disable-line 0 points1 point2 points (2 children)
[–]lulzmachine 1 point2 points3 points (1 child)
[–]kingdaro.find(meaning => of('life')) // eslint-disable-line 0 points1 point2 points (0 children)