Skip to content

Move irrefutable/binding matchers to a different syntax #283

Closed
@tabatkins

Description

@tabatkins

(This is part of several issues stemming from my discussion with Yulia.)

Currently, the "plain ident" part of the matcher syntax space is taken by irrefutable matchers (except for a small carve-out for some literal constants). That is, in when([null, a]), the item is in the array matcher is a literal matcher for null, and the second always succeeds and binds the value to a.

This syntax is pretty nice because it means that, for many simple patterns, we look identical (and act nearly identical) to destructuring - [a, b] binds the first two values out of an array to a and b in both contexts. (Patterns just also do a length-check, which destructuring doesn't.)

However, in more complex cases it's not quite as obvious. When binding a value and doing further matching, the current spec uses and, like [a and ("foo" or "bar")] to pass the value to both the irrefutable matcher (to produce a binding) and the other matcher. While I find this pretty reasonable, multiple people have expressed confusion about this syntax pattern.

As well, this is very valuable syntax real estate. Yulia wants to be able to invoke simple function-based custom matchers (see #282) with as little syntax weight as possible, but right now you have to use the ${} interpolation matcher. Ron wants to be able to use this space for their Extractors proposal; it's not technically clashing (Extractor patterns require a trailing () or {}) but it's weird to occupy the same space.

Finally, several people have expressed misgivings with the current proposal's carve-out of a few literal values - Infinity and undefined are both technically valid bindings that you are allowed to assign to, but we recognize them as literal matchers instead of irrefutable matchers.


I think we can address all of the above by moving irrefutable matchers to a slightly different syntax. Specifically, I propose:

  • Irrefutable matchers should be spelled as <ident>. Another possibility is let <ident> (and const <ident> alongside, possibly var <ident> as well).
  • Plain idents are treated as custom matchers; that is, ${foo} and foo are exactly identical.
  • We allow a very restricted set of operations in this space; probably just unary-plus, unary-minus, and possibly dotted property access. This lets us remove the special-cases for unary plus/minus on numeric values (-2 isn't actually a number, it's an unary-minus expression on the number 2); it lets authors compare against the negative of a variable without having to write ${-foo}; and it lets us at least do Option.Some or similar.

Avoiding more expression syntaxes both keeps us away from grammar issues, and leaves us more breathing room for additional patterns, like Extractor Patterns or similar using Foo().

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions