Skip to content
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

let and relationship to extractors #314

Closed
littledan opened this issue Jan 30, 2024 · 7 comments · Fixed by #293
Closed

let and relationship to extractors #314

littledan opened this issue Jan 30, 2024 · 7 comments · Fixed by #293

Comments

@littledan
Copy link
Member

If I understand correctly where your current draft is (#313), then it looks like let is required to establish bindings within patterns. I definitely see how this is conceptually cleaner and more composable than earlier forms, though it's a bit syntactically heavy. Is this the champion group's current direction?

My understanding is that let is important to subsume the need for ${}, which was a way to distinguish between what's establishing a new binding, and what refers to literals to be matched, extractors, or other things to be read from outside of the pattern.

However, extractors show another path to distinguish between the pattern and the bindings--if it has parens after it, it's an extractor; otherwise it's a variable being assigned to. Would it work for pattern matching to apply the same mechanism here? This could be nice for consistency between forms as well as terseness, though it would reduce the other aspects of consistency which let introduces.

@ljharb
Copy link
Member

ljharb commented Jan 30, 2024

I don't think it would, because we have a need to use the already available and massive corpus of predicate functions.

@littledan
Copy link
Member Author

Could you elaborate on that? I don't understand how you want to embed predicate functions and how this relates to let.

@tabatkins
Copy link
Collaborator

Two important use-cases we want to ensure work as easily as reasonably possible are (1) matching against the value of an existing variable, and (2) matching using an existing predicate function (rather than requiring predicates to be specifically written against the pattern-matching model, using [Symbol.customMatcher]/etc.

Both of these compete for the "plain ident" syntax space with bindings, and since we have the "well do you want let or const or var" problem anyway, the easiest path forward is put bindings behind the declaration prefix, and let vars/preds use plain idents (along with custom matchers, which is how predicates are supported anyway (a built-in Symbol.customMatcher property on Function.prototype)).

(Technically, this collides these use-cases; you can't compare the subject with an object that has a custom matcher on it. In practice, this is pretty unimportant; comparing functions by object identity is a rare pattern. You can drop down to if() patterns when it's actually required.)

@littledan
Copy link
Member Author

It'd be great if someone could give an example of using a predicate function, showing how the syntax differs from matching against equality of a value that's in a variable.

@tabatkins
Copy link
Collaborator

const CR = 0x0d;
const LF = 0x0a;
function isWhiteSpace(ch) {...}

match(someChar) {
    CR or LF: doSomething();
    isWhiteSpace: doSomethingElse();
    default: doAThirdThing();
}

@littledan
Copy link
Member Author

Thanks for the example. Yes, I agree that these are important. Personally, I didn't mind the ${ } syntax to handle that case, though I understand that the rest of the committee strongly disliked it. Another option is to have some particular kind of syntax for this case, of matching against a variable which is a predicate, or something to be compared for equality. For example, with the placeholder keyword kw (since I don't have a good name in mind):

match(someChar) {
    (kw CR) or (kw LF): doSomething();
    kw isWhiteSpace: doSomethingElse();
    default: doAThirdThing();
}

@Jack-Works
Copy link
Member

in this case, we have this (not as a group consensus but mentioned in the drafted spec):

match(someChar) {
    (=== CR) or (=== LF): doSomething(); // "===" pattern
    isWhiteSpace: doSomethingElse(); // custom matcher
    default: doAThirdThing();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants