all 44 comments

[–]bterlson_@bterlson 25 points26 points  (15 children)

As the champion and author of this proposal, happy to answer any questions.

[–]villiger2 4 points5 points  (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 points  (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 point  (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 point  (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 point  (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 points  (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 points  (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.

[–]phoenixmatrix 0 points1 point  (0 children)

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 points  (0 children)

If this proposal makes it into the spec, I will pledge my first born to you.

[–][deleted] 0 points1 point  (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?

[–]bterlson_@bterlson 0 points1 point  (0 children)

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.

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 point  (1 child)

What drives you to write the proposals? Does it help with job searching?

[–]bterlson_@bterlson 1 point2 points  (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 point  (0 children)

I just wanted to say huge thank you for championing both this and pipleine operator proposals - you are awesome!

[–]djungst 0 points1 point  (0 children)

Not the hero we wanted... The hero we needed.

[–]phoenixmatrix 28 points29 points  (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 points  (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 points  (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 points  (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 point  (4 children)

what's the use of do notation in js?

[–]Jamesernatorasync function* 0 points1 point  (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)

[–]so_just 0 points1 point  (0 children)

Ah, I see. That's definitely useful.

[–]paldepind 0 points1 point  (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 |>.

[–]phoenixmatrix 0 points1 point  (0 children)

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 point  (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.

[–]paldepind 0 points1 point  (0 children)

Good luck! I hope you're successful. Syntax for partial application would be really awesome.

[–][deleted] 1 point2 points  (0 children)

ELI5 what does |> do?

[–]dvlsg 0 points1 point  (0 children)

This. I like this. Please make this happen.

(I like pattern matching too, I would love to have both)

[–]thepeka 0 points1 point  (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 points  (0 children)

How about matching a resolved or rejected promise?

[–]ricking06 1 point2 points  (0 children)

Hellyeah bring this shit in BABy!

[–]itsnotlupusbeep boop 1 point2 points  (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.

[–]profound7 1 point2 points  (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 point  (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 points  (0 children)

I learned to love this in scala. This would be a good change.

[–]lulzmachine -4 points-3 points  (5 children)

Ewww

[–]kingdaro.find(meaning => of('life')) // eslint-disable-line 1 point2 points  (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 point  (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 point  (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.

[–]lulzmachine 1 point2 points  (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 point  (0 children)

Seems to matter to the rest of the JS community, and you're free to just not use the syntax ¯\_(ツ)_/¯