-
Notifications
You must be signed in to change notification settings - Fork 89
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
Drop as
, rely on and
#219
Comments
My concern is what I've described before: without |
Again, that's assuming that the argument to |
Also you can already write that as |
I don't think "it looks like an object pattern but is not" is actually a problem, because it would either work the same, or syntax error, and you'd immediately learn the difference. To your second comment tho - that's a fair point - if object/array patterns allow defaults, and defaulting them bypasses the presence check, then perhaps there's no need for |
We've had this discussion previously, and those aren't the only possibilities. If the matchable has a This is particularly confusing with custom matchers, since they have the same prelude: You can just destructure the value in the body. Pattern-matching should be about matching patterns. |
I'm also moderately opposed to dropping I also agree with Tab's assessment that allowing destructuring patterns after |
You really think teaching people |
I think |
??? I have no idea what you mean here. The point of |
Another advantage to favoring the use of Compare these: when ({ user: { groups: [firstGroup, ...others] as groups } as users })
when ({ user: users and { groups: groups and [firstGroup, ...others] } }) I would argue that the second version is more readable. The problem with the first, is when you see something like To me, this means the only time I would ever use the |
Yeah, I also think this is a pretty significant readability win. |
@tabatkins it's something i'll want, without further pattern-matching, the great majority of the time. With defaulting, I can get it with |
@mpcsh - As for this point, I would argue that the learning curve is easier if we drop "as", not harder. Less operators means less to learn. Users will have to learn how to use the "and" operator anyways, and will learn that they're able to bind to identifiers using "and" just like they can do with "as". Plus, I like to avoid feature overlap wherever it's sensible to do so. It's better to give developers clear paths instead of multiple almost-the-same options that they have to mentally bikeshed over whenever confronted with a choice (Should I use "and" or "as" here? What's the common practice out there for this scenario? Does my style guide say one thing or the other? Maybe I'll google around). |
Yes, I do. Though I think this thread has mostly run its course as a matter of opinions - I don't think we can reach any meaningful conclusion without conducting actual research on this topic.
We can all make perfectly cogent arguments as to why it will be easier or harder to teach |
What about having two proposals one with |
I'm not sure I really understand your viewpoint @mpcsh (but maybe you could expound a bit?). For someone learning the pattern matching syntax, how is learning both "and" and "as" operators simpler than just learning an "and" operator? Perhaps, when you say "easier to teach", you're just talking about the complexity of teaching how to bind an intermediate pattern, and aren't talking about how difficult it is to teach the entire syntax construct of pattern matching? If that's the case, then yes, I would agree that it's easier to teach how to use a dedicated binding operator to bind, over teaching the more general-purpose "and" operator (you wouldn't need to do a study to convince me of this). If we follow @tabatkins suggestion and make "as" bindings only allow identifiers on the RHS (not destructuring patterns), then "as" would be nothing more than a strict subset of the "and" operator. It would be as if we introduced a new "<-" operator that works exactly the same as "=", except you can only destructor on the LHS. e.g. // These two do the same thing
const { point } = data
const { point } <- data
const x = data // But "=" can also assign without destructuring
// These two do the same thing
when ({ point } and data)
when ({ point } as data)
when ({ point } and ^Thing) // But "and" can also pattern match on the RHS. Any point we make in favor of keeping the "as" operator, would also be a point in favor of introducing this new "<-" operator. For example, I could argue that it would be slightly easier to teach destructuring with "<-" then "=", because "<-" is a dedicated destructuring operator and doesn't do anything else. OK, maybe I'm falling a bit into the "invalid analogy" logical fallacy there. I will say that the one thing that "as" has going for it is the fact that it reads a little nicer. But I'm not sure "better wording" is enough of an argument to introduce a new special-case operator that provides no new functionality. There's struggle in trying to even get a new filter function through, that behaves almost identically as the current one, but has better wording to make it clear if you're "filtering for" or "filtering out" (See these meeting notes which shows people weren't too optimistic about the idea) - if a new function is struggling to get through that's trying to achieve this objective, I'm not too optimistic about new syntax. |
My reasoning here is that I believe that top-level irrefutable matches are conceptually hard. Introducing an I do think the hypothetical |
While I'm still in favor with dropping "as", I'll note another point in favor of keeping it. "and" is a pattern-matching only operator. It wouldn't make sense to allow "and" when doing destructuring. We could provide "as" as its own proposal, which will modify both destructuring and pattern-matching, allowing you to do intermediate bindings while destructuring. I know there's many people who would love to have this kind of behavior while destructuring. |
(see conclusion in #188) |
Since we're committed to having
and
(with some spelling), this gives us an opportunity to simplify the syntax, particularly around custom matchers.Right now, at any given point in a pattern, you have a choice - you can either bind the value under consideration to a name with an ident matcher, or further pattern-match it with any other matcher. If you want to do both, you append the
as
clause to the "other" matcher, likewhen ([a,b,c] as list) ...
.However, the
and
combinator lets us do this already, by passing the value to both an ident matcher and a further pattern:when (list and [a,b,c]) ...
. Since the ident matcher always succeeds in matching, this has the same matching behavior as just providing the second matcher, but it provides an additional binding.This particularly lets us avoid some confusion around custom matchers, which already have their own subordinate
with
clause. Starting fromwhen ^Foo with [a,b]
, currently you can bind the value before passing thru the custom matcher withwhen (^Foo with [a,b]) as preval
, or the value after passing thru the custom matcher withwhen ^Foo with ([a,b] as postval)
.when ^Foo with [a,b] as mysteryval
is invalid, as it's ambiguous.Instead we could just use
and
to write the patternswhen preval and ^Foo with [a,b]
orwhen ^Foo with (postval and [a,b])
.That's one less syntax complexity to worry about, with zero loss of functionality and ~zero gain in verbosity. The only concern is that people might not intuitively grasp that
and
lets them do this sort of binding, while that's the entire point ofas
so it's obvious. But I suspect this is the sort of thing that will show up early in tutorials and just become a known pattern, so I'm not too concerned about it.Thoughts?
The text was updated successfully, but these errors were encountered: