tc39 / proposal-pattern-matching

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

Sole identifier pattern #248

Closed Jack-Works closed 2 years ago

Jack-Works commented 2 years ago

If the matcher is solely an identifier pattern (eg when (x):), it must be the final match clause (as it is, essentially, a default matcher), or else SyntaxError.

Currently, solely identifier pattern is a Syntax Error when it is not at the last, but it limits our syntax space in the future:

Now, NaN, Infinity, undefined is a special identifier pattern, we can write code like this:

match (val) {
    when (NaN): NaN
    when (Magic): console.log("default case with", Magic)
}

The current design makes us impossible to add any new special identifier pattern in the future because it will be a breaking change.

Let's say, we added a new special identifier pattern called Magic, the code above will be broken. When a value that is not matched by the NaN pattern and our new Magic pattern, it will be a TypeError at runtime!! (thanks @hax for raising this problem)

Solution

  1. Change all sole identifier pattern that is not NaN, Infinity, undefined to an early Error.
  2. For the use case of default binding, we use this:
match (val) {
    when (NaN): NaN
    default with Magic: console.log("default case with", Magic)
}

Or

match (val) {
    when (NaN): NaN
    default(Magic): console.log("default case with", Magic)
}
ljharb commented 2 years ago

That is the intention, as we believe there is no possible identifier pattern we could add in the future.

Jack-Works commented 2 years ago

That is the intention, as we believe there is no possible identifier pattern we could add in the future.

🤔 why? Leaving some space for us is always good.

By the way, I think default (binding) is more readable than when (binding) for its purpose (the default binding).

ljharb commented 2 years ago

there’s no need for a binding on the default one; when (identifier) is behavior that falls out of being able to have an irrefutable match nested inside arrays and objects.

In other words, there is no choice but to allow a top-level identifier pattern, because we must have a nested one, and they must be consistent.

tabatkins commented 2 years ago

Also, this isn't just about the 'sole identifier must be last' part - any identifier used in a pattern will change meaning in this way if JS ever adds more literal identifiers.

Jack-Works commented 2 years ago

yes, I agree. this is impossible to solve, so I thin the status quo is good