This would be great for object enum members. My proposed change would simply be adding this:
LiteralMatchPattern :
`(` Expression `)`
The parentheses prevent it from being interpretable as a LHS, so it's pretty unambiguous to add and easily parsed.
(Side note: you may want to change Variable to BindingIdentifier within your IdentifierMatchPattern grammar.)
This seems like it overlaps with variable pinning.
I worry that this would cause confusion because of the close correspondence with arrow function:
const y = 'why'
match (x) {
(y) => ..., // y is "why"
y => ... // y is x
}
It also means that a separate suggestion that's been made, to use () as a fallthrough (because it's like arrow functions like () => 'foo') would no longer be available. Or any other reason to parenthesize these.
On top of that, it would create a parsing conflict with Extractors:
match (x) {
// this will either try to invoke `Foo` as a function,
// or syntax error because no matcher
// or act like `Foo 1`.
// This seems confusing?
Foo (y) => ...
// This is a thing you can actually do right now:
Foo x => ... // Foo is an extractor, x is a BindingIdentifier
}
Thanks for the suggestion about BindingIdentifier btw! I'll get that fixed right quick.
Is Foo(x) already a valid match case?
Also, the concept is for things like this (part of a Redux reducer, adapted from my old strawman):
import {
SELECT_SUBREDDIT,
INVALIDATE_SUBREDDIT,
REQUEST_POSTS,
RECEIVE_POSTS
} from './actions'
function posts(
state = {
isFetching: false,
didInvalidate: false,
items: []
},
action = undefined
) {
return {...state, ...match (action) {
{type: (INVALIDATE_SUBREDDIT)} => ({didInvalidate: true}),
{type: (REQUEST_POSTS)} => ({
isFetching: true,
didInvalidate: false
}),
{type: (RECEIVE_POSTS), posts, receivedAt} => ({
isFetching: false,
didInvalidate: false,
items: posts,
lastUpdated: receivedAt
}),
_ => ({})
}}
}
And welcome re: BindingIdentifier 馃憤
@isiahmeadows I'm working on fixing up the grammar now (I actually started looking stuff up in more detail after you mentioned BindingIdentifier, but the MatchExtractorReference meant to support Foo(1,2,3) x, so you can call a function to generate an extractor for you. I'm working out what grammar to actually use for this, though (just a matter of continuing to hash out the current grammar. My syntax sketch looks very different right now, and I'll push it out in the next few days. Just takes time.)
For mine, it'd be generating not an extractor, but a literal === check against a value specified in a variable. Thought I'd clarify what I meant here.
Note: After working more on the grammar, I think we shouldn't do this, because it would introduce a grammar ambiguity. Furthermore, I believe this defeats a lot of static semantics around how MatchPattern works that I think are important for optimization (it would essentially force a lot of statically-determinable behavior dynamic). Or, if the semantics are "do Object.is comparison on the result of Expression", that seems to be fairly low-value. See #71, and specifically, the MatchExtractorReference expression.
match (x) {
{type: Const(INVALID_STATE) _} => ...
}
or:
match (x) {
{type} if (type === INVALID_STATE) => ...
}
or even incorporating a pinning operator would be good alternatives to this, I think?
Another idea is to make MatchBinding optional if you find a CallExpression:
match (x) {
{type: Enum(INVALID_STATE)} => ...
// is the same as:
{ type: Enum(INVALID_STATE) _} => ...
}
But that feels weird and might get confusing? Maybe?
I'm more concerned about functionality than necessarily the syntax used (as long as it isn't extravagant).
Implementing a new match "operator" of sorts would also be acceptable in my book. I do find the call expression special casing a bit weird and odd in comparison to the rest of the proposal.
@isiahmeadows functionality-wise, what you're describing is already possible with only slightly more typing:
case (x) {
x if (x === SOME_VAR) => ...
}
For now, I'd like the freedom to reserve () inside match expressions for other purposes, specially while we hash out what extractors are going to actually look like. I think the request in this issue is a syntactic optimization that definitely applies to a common use-case, but I'm not sure I like the specific solution offered here.
I'm not super attached to my solution (it was a quick/easy hack) - just thought I'd reinforce that.
The only nice thing about having this Object.is(expression-result) is that it makes Symbol-matching easier, but given that guards accomplish that with only slightly more syntax weight, I'm fine with punting this from the v1 proposal and seeing if we need it later. Parenthesized expressions will currently be a syntax error, so we have extension space.
I think the if escape hatch seems good enough for now, and discussion seems to have died down and nothing more seems to need discussion, so I'm gonna close this for now.
Hey @zkat is there an issue tracking using functions to generate an extractor? I personally think that'd be rather troublesome and would love to jump into the discussion.
@mrkev it's a separate proposal altogether: https://github.com/zkat/proposal-collection-literals