tc39 / proposal-pattern-matching

Pattern matching syntax for ECMAScript
https://tc39.es/proposal-pattern-matching/
MIT License
5.46k stars 89 forks source link

Having both parens and a colon for each case are unneccessary punctuation #249

Closed Jamesernator closed 2 years ago

Jamesernator commented 2 years ago

In the current proposal parentheses are required around each pattern, however this restriction does cause certain usages, particularly custom matchers to become a bit of a symbol soup:

match (x) {
   when (${Number}): someValue;
   // ...etc
}

It's worth pointing out that case ...: in switch doesn't require parentheses, this is because the : already delimits where the, errr, "case" ends and the body starts. Other constructs like if () need parentheses precisely because the body has optional {} AND there is no other delimiter in the if to split the condition.

This is a new grammar construct so it doesn't need to be constrained by grammar rules on if (), we could easily make the parens optional similar to how case already works and just be able to write:

match (x) {
    // This is more similar to switch, which match is more similar to
    when ${ Number }: someValue;
    when 2: someValue;
}
ljharb commented 2 years ago

It doesn't need to be, but the champion group prefers it to be - for explicitness, readability, and to have boundary characters.

Punctuation is a good thing; it serves an important purpose.

This seems like a duplicate of #182.

Jamesernator commented 2 years ago

readability

I would argue it decreases readability, it turns common usages into large syntax soup, particularly the custom matcher syntax which I pointed out above. I've never seen any complaints about switch/case being less readable because of no parens.

boundary characters

Again, : is already a boundary character, this proposal adds two boundaries, the parens and the : despite the fact there would be no ambiguity if just one were chosen.

Punctuation is a good thing; it serves an important purpose.

Having both serves precisely zero purpose here, that's exactly why I opened the issue.

ljharb commented 2 years ago

It’s certainly subjective, but the champion group is aligned on this, and it’s what we’ll be presenting at the meeting later this month.

Jamesernator commented 2 years ago

For the record I think removing the : would be another alternative. The thing is the current proposal is consistent with precisely nothing in the language.

It's not consistent with switch/case due to required parens, and it's not consistent with if/while due to the require :. Effectively we have three syntaxes:

// if/while statments
if (x) BODY
// case clauses
case x: BODY
// when clauses
when (x): BODY
// if pattern clauses
if (x): BODY

Also if do expressions advance then we will have two similar constructs that have arbitrarily inconsistent syntax:

match (x) {
   // Colons required here
   if (x > 10): EXPR;
   if (y > 20): EXPR;
}

do {
   // But not here?
   if (x > 10) EXPR; // optionally bracketed
   else if (y > 20) EXPR;
}

In fact the proposal even seems to expect do expressions to progress as is, given it uses them in all of it's motivating examples.

ljharb commented 2 years ago

Yes, we do expect that.

Pattern matching is something distinct from everything else in the language; it’s fine that its syntax isn’t the same as something that already exists.

theScottyJam commented 2 years ago

I can see the value in having both, and I think I personally prefer it. Pattern-matching is a pretty complicated control structure that can have a lot going on in there. The parentheses can be used to section of specific regions of the LHS, while the colon provides a visual signpost for when the LHS is done and the RHS starts.

So yes, in the simple case, the parentheses and colon is redundant. But in more complicated scenarios, they provide good visual signposts.

match (x) {
  // Compare this
  when (x & { a: 2, b: #{z < 3} }) if (x > 0 && x < 10): x < 3
  // to this
  when x & { a: 2, b: #{z < 3} } if x > 0 && x < 10: x < 3
}

Now, you may still prefer the latter example, beauty is in the eye of the beholder. But, this should at least show that the parentheses and colon are not doing the same thing.

concavelenz commented 2 years ago

Agreeing with @Jamesernator here. I don't see why this syntax would be unique. You can use parentheses if you like, but I don't see any reason to make them required if a ":" is used as a seperator. Personally, I favor when () ... but I could see either as being pretty reasonable.

ljharb commented 2 years ago

Another consistency issue this would cause - the if MUST have parens around the condition, to be consistent with actual ifs - and when pattern if (condition) would be internally inconsistent.

tabatkins commented 2 years ago

Yup to all of this. We need parens or else when and if are inconsistent (and we need parens on if to be consistent with usage elsewhere in JS), and the champions have tried out a lot of variations on the separation (no character, : character, -> characters, etc) and come to the conclusion that having a separator is a useful visual indicator between a potentially-complex matcher and a potentially-complex value, letting the eye parse the distinction more easily.

The spec used to have no separator, we worked with that for quite a while, and we collectively decided having a separator would be better. This is def staying as it is for now unless there's a very strong reason to do otherwise.