Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advices from already existing pattern matching for Javascript #25

Closed
leonardiwagner opened this issue Jul 5, 2017 · 10 comments
Closed

Comments

@leonardiwagner
Copy link

Hello, I'm a contributor from z , a native pattern matching for Javascript: https://github.com/z-pattern-matching/z, yes, native pattern matching for Javascript exists for a while.

I have some advices about working 2 years with pattern matching in Javascript world, and seems you guys are missing some stuff with this proposal:

1. In the beginning I tried to make it more genuine pattern matching possible, as Haskell is, more like functional programming as I could do in Javascript. The article Why type classes aren’t important in Elm yet described why that approach failed. The Javascript community don't adopt the strictness of a genuine pattern matching and Javascript programmers aren't really acquainted with functional programming. As soon z became "less Haskell" and "more Javascript", it started to shine and being adopted instead being just a fancy-feature-which-is-used-on-experimental-projects-only.

2. At first I got mad being limited under original ES2015 syntax, I wished to have more power being able to change the syntax to bring more power, but now I realized how good it was! The challenge about being trapped into the original syntax made me be creative to bring the power I wish in the "Javascript Way", now every expert or beginner programmer which take a look on z pattern matching code understands at first and is familiar, being experienced on functional programming or not. Still pattern matching, still Javascript, still simple and still powerful.

3. TL;DR; be Javascript, less is more, eg. why the fancy monster else to be exhaustive pattern in the proposal code:

const result = a => match (a) {
    { x: 0 }: someCode(),
    else: {
        throw new Error("this is the default");
    }
}

if we can achieve that naturally? as in z

const result = match(a)(
  (x = 0) => someCode(),
  (x) => throw new Error("this is the default") 
)
@ljharb
Copy link
Member

ljharb commented Jul 5, 2017

I don't think an implicit default is a good thing. z looks very interesting tho!

@bterlson
Copy link
Member

bterlson commented Jul 5, 2017

These approaches seem roughly equivalent in terms of patterns they can express - take this proposals patterns, put them after the = and it's roughly the same. With changes to identifiers as suggested in #11 and outer binding in #10, they would be even closer syntactically (and else would be removed). E.g.

const result = a => match (a) {
    { x: 0 }: someCode(),
    else: {
        throw new Error("this is the default");
    }
}

becomes

const result = a => match (a) {
    { x: 0 }: someCode(),
    _: { // could be any identifier, _ used by convention
        throw new Error("this is the default");
    }
}

@ljharb
Copy link
Member

ljharb commented Jul 5, 2017

@bterlson not sure where the best issue is to suggest this, but what about the following?:

const result = a => match (a) {
    { x: 0 }: someCode(),
    * as _: { // could be any identifier, _ used by convention
        throw new Error("this is the default");
    }
}

That would allow for a custom identifier; it would avoid imbuing special magic powers to _; it would avoid a bikeshed over the identifier name; it could be identifierless with *:; etc?

@bterlson
Copy link
Member

bterlson commented Jul 5, 2017

With #11, _ works as is for default case as a binding identifier (and would bind that part of the pattern, in this case the entire value). A reason for special powers for _ is just to avoid the error when using it in larger patterns where you want more than one hole.

as is probably an extension I should mention in this proposal (but also impacts basic destructuring).

@7fe
Copy link

7fe commented Jul 5, 2017

@ljharb I would prefer introducing more operators then introducing more keywords for various reasons which I have mentioned.

@leonardiwagner
Copy link
Author

I don't think an implicit default is a good thing.

@ljharb I think saying implicit is not right, because when you match, you match something, let's take a look

const result = match(1)(
  (x = String) => 'is string',
  (x = Date) => 'is date',
  (x) => `is something else: ${x}` //proposal "else" or "default"
)

it says "match 1", as none of patters above matched, just match the argument, it's not hidden,implicit or magical, it's just what is written, also this is the very way pattern match works on Rust and F# (mentioned inspirations for this proposal), and in old and modern programming languages with pattern matching. Every time you need to match anything which didn't apply to matches above, just match.

Creating a keyword for that is a feature beyond pattern matching, and is not necessary.

@ljharb
Copy link
Member

ljharb commented Jul 6, 2017

Fair point - would it be a syntax error to include "just the argument" multiple times, or in any position but "last"? If not, that seems dangerous/bug-prone.

@leonardiwagner
Copy link
Author

@bterlson that pattern matching in Haskell will compile and execute fine:

matchNumber :: Integer -> [Char]
matchNumber x = "It will print the number"
matchNumber 1 = "It will never reach even if number is 1"
matchNumber x = "It will never reach"
matchNumber x = "It will never reach"

main = print $ matchNumber 1

My argument is because it can happen with any pattern, the "default" is just the most embracing one, but you can have much others which will lead you to the same "danger", see:

{x: 1      }: 'Number 1',
{x: Number }: 'Any number',
{x: 2      }: 'Another number will never reach here due pattern above'
{x: x      }: 'Another number will never reach here, and is not my fault now!'

So "protecting" only the default pattern won't help much about that.

Besides me not being a senior Rust or F#, or even Haskell programmer, I didn't hear complains about that being bug-prone yet, as any other match can apply the same effect 😕

@leonardiwagner
Copy link
Author

leonardiwagner commented Jul 6, 2017

@bterlson I took a look on #10 and #11 and there are good directions! I wanted to share my experience to expose I had that push to create stuff like "let's put else, as or is to make this powerful..etc" and it looked like a Frankenstein. I must confess that I got that Frankenstein feeling when I read the proposal code at first, it looks like anything but Javascript! hehe

When z became pure ES2015 alike, it looked like Javascript. People started to understand because it just felt natural as it is in any other languages, such mentioned inspirations Rust and F#, and I also felt glad because I realized it became a better tool indeed, with same amount of power.

I'm not asking to change in this proposal, only for share: silly stuff like using the = sign for matches, object notation only for object matching eg.: (x = {name: "John"}), no much code to compare types (x = String) , really made a huge difference. Anyone can understand, people still feel it's Javascript, and is also pattern matching after all. I know we need to innovate, but sometimes innovating is doing new things in the very same way also!

I hope I have at least helped to bring new insights, this proposal is very good!

@zkat
Copy link
Collaborator

zkat commented Mar 25, 2018

Hey y'all! #65 has gotten merged, and a lot of issues have become irrelevant or significantly changed in context. Because of the magnitude of changes and subtle differences in things that seem similar, we've decided to just nuke all existing issues so we can start fresh. Thank you so much for the contributions and discussions and feel free to create new issues if something seems to still be relevant, and link to the original, related issue so we can have a paper trail (but have the benefit of that clean slate anyway).

@zkat zkat closed this as completed Mar 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants