2024-09-03 [08:27:15.0126] @room augh, I ended up with too much on my plate at the tail end of last week and am not ready for this meeting. I'm so sorry but gotta cancel, do y'all have availability later in the week? Or else next Monday? [08:33:09.0312] i can do the same time on friday [08:42:53.0546] I also want to sleep early tonight 👀 [08:48:15.0727] I can also do Friday at the same time, or next Monday [08:48:40.0951] if it can be 1 hr earlier that will be great [08:50:45.0035] i can't do any earlier unfortunately, i have to drop my kids off at school [08:50:59.0337] why don't i move it to friday, and we can reschedule further if needed 2024-09-06 [08:37:02.0656] Sorry, I clicked Yes on the invite but didn't actually ping the room - yeah, this morning is great. [09:05:44.0699] @room just in case anyone else is joining, meeting is starting now [09:06:00.0475] @room just in case anyone else is joing, meeting is starting now [09:43:35.0901] meeting notes: https://github.com/tc39/proposal-pattern-matching/issues/332 [10:01:34.0253] Regarding the contextual keyword issue, it's not that having both prefix and infix contextual keywords is impossible, but that they introduce complexity that must be managed, and that complexity could easily grow out of control. When new syntax would introduce an ambiguous parse, we must always choose an approach that favors backwards compatibility. Given the example: ``` for (using is of and [not/a+"/g]; b++; [/"/g, 5]) ``` We would have to break down the grammar to align with ECMAScript syntax roll-out: - `for..of` shipped before `using` - `using` will probably ship before `is` Prior to pattern matching, the above parse would treat `is` as an identifier and `and [not/a+"/g]; b++; [/"/g, 5]` as an expression. Therefore we would need to maintain that behavior. As waldemar points out, this is a complex issue that will resurface each time a proposal seeks to add a new feature. Unfortunately, I don't think just choosing `~=` is a solution to the overarching problem. There are a limited set of punctuators, and combining punctuators in more and more obscure ways will do little to convey their meaning, whereas contextual keywords give us a far wider space for future proposals to leverage. IMO, finding solutions to make it easier to address the prefix/infix complexity, such as automated validators, may be worth pursuing. [10:26:25.0333] I'm still giggling over the fact that `for(of of of)` is valid today. [10:26:43.0987] ```js var of = [1,2,3]; for(of of of) console.log(of); ``` [12:19:51.0187] personally i think we won't be adding so many keywords of either type that the complexity is a problem [12:46:33.0986] The issue isn't convincing you, tho, it's convincing the committee. [13:39:47.0084] very true. but i'm hoping that "there's a list of ~10 exceptions" complies with the priorities of constituencies stuff given that it makes the language better, is convincing 2024-09-16 [08:03:48.0367] do we have meeting today [08:13:52.0917] It seems like no? [11:05:50.0404] I’m on a plane, so i couldn’t attend 2024-09-24 [09:06:48.0389] TabAtkins: any update on slides? [09:23:41.0531] Not yet, but I have free time this afternoon at TPAC, I'll bang them out. [09:52:36.0278] awesome, that'd be great. agenda deadline is in 2-3 days [09:52:46.0734] * awesome, that'd be great. agenda deadline is in 2-3 days, and we should all review them before we add advancement to the agenda [10:26:51.0683] yeah, np [14:02:31.0788] Did we end up deciding one way or the other on whether we're keeping the `when` prefix or just dropping it? 2024-09-25 [17:46:33.0609] My preference was to drop it, I'm not sure where others stand [18:06:43.0374] aight, first draft is https://docs.google.com/presentation/d/1ckdNcRpzMB7oV91k98gNkXxVtwkzqIv0vALPffSaU44/edit?usp=sharing [18:06:50.0822] i'm assuming "no `when`" [18:12:22.0989] new slogan: "no when, no how" [21:25:13.0432] my strong preference is to keep it [21:25:24.0185] explicit > implicit [21:25:48.0237] but for stage 2 i'm content saying "we'll decide to keep or drop the `when` prefix before stage 2.7" [21:26:33.0374] slide 4, `undefined` literal - `null` is always a literal, no exceptions [21:26:45.0048] * slide 4, `undefined` literal - `null` is always a literal, no exceptions, no matter what we decide [21:27:07.0948] oh oof, we decided not to make undefined and the infinities special? [21:27:15.0816] * oh oof, we decided not to make undefined and the non-finites special? [21:27:39.0937] when you say `ident`, let's say `Identifier` in backticks, to be explicit about the grammar production [21:28:48.0749] for slide 6, falsiness implying "no match" is fine, and a *primitive* truthy value implying "match" is fine, but an object should be the `{ matched: boolean, value: unknown }` schema, yes? [21:29:31.0239] for slide 7, this is wrong - it needs to check for `Object(3)` - ie, boxed numbers - also, same for all primitive wrappers. `typeof` only detects primitives. [21:30:39.0999] slides 14 and 15 should reference caching. [21:30:44.0508] globally, `s/falsey/falsy` [21:31:32.0933] * slides 14 and 15 should reference caching, even though it's explained on slide 18 [21:32:33.0156] i'd love more elaboration on slide 17 also [21:32:43.0135] overall, awesome, this is a great first draft :-) [21:44:12.0887] > <@tabatkins:matrix.org> i'm assuming "no `when`" current spec is no when [21:44:34.0396] 👍 [21:44:49.0683] Examples in the readme are still all over, wasn't 100% sure [21:44:52.0128] I'll fix [21:47:03.0078] > <@ljharb:matrix.org> for slide 6, falsiness implying "no match" is fine, and a *primitive* truthy value implying "match" is fine, but an object should be the `{ matched: boolean, value: unknown }` schema, yes? Nah, remember we changed the model to let you tell which mode you're in (bool or arglist); in the bool mode it's just being a bool that matters, and in the list mode we expect a list but allow for bools [21:47:32.0174] hm, ok [21:49:09.0796] > <@ljharb:matrix.org> slide 4, `undefined` literal - `null` is always a literal, no exceptions currently in the spec, `undefined` is not a literal, it will find the "undefined" variable which might be shadowed. if we have concensus that this should not be like this, plz open an issue and I'll fix the spec [21:50:05.0979] originally we had `undefined`, `Infinity`, and `NaN` as "special", where they'd never be identifiers and always refer to the intuitive values [21:51:29.0329] > Any non-reserved ident sequence, with dots and/or square brackets. We have a little bit more than that. `this`, `MetaProperty`, `super` and `PrivateIdentifier` can also involve this. (see `PatternMatchingMemberExpression`) [21:54:00.0732] slide 6 > Function is invoked with (subject, {matchType:“boolean”}). it's f(subject, hint, receiver) right now. e.g. `f(subject, "boolean", thisValue)` [21:54:16.0988] * slide 6 > Function is invoked with (subject, {matchType:“boolean”}). it's `f(subject, hint, receiver)` right now. e.g. `f(subject, "boolean", thisValue)` [21:55:20.0199] slide 7: actually we unbox boxed primitives (https://tc39.es/proposal-pattern-matching/#sec-number-%symbol.custommatcher%) [21:55:25.0755] * slide 7: actually we unbox boxed primitives (https://tc39.es/proposal-pattern-matching/#sec-number-%symbol.custommatcher% ) [21:56:51.0755] side 8: I think it's better to add `hint, receiver` to match the spec https://tc39.es/proposal-pattern-matching/#sec-function.prototype-%symbol.custommatcher% [22:06:47.0430] > If return value is `true` (not truthy!), same as returning `[]`. slide 16. we don't have this in the spec, and I think this behavior might be a footgun. if a function returns `true`, you should use it like `f: ...`. Use it like `f(...): ...` is always an error [22:07:21.0984] * > If return value is `true` (not truthy!), same as returning `[]`. slide 16. we don't have this in the spec, and I think this behavior might be a footgun. if a function returns `true`, you should use it like `f: ...`. Use it like `f(...): ...` is always an error current in spec: https://tc39.es/proposal-pattern-matching/#sec-invoke-custom-matcher [22:10:28.0709] > <@jackworks:matrix.org> > If return value is `true` (not truthy!), same as returning `[]`. > > slide 16. we don't have this in the spec, and I think this behavior might be a footgun. if a function returns `true`, you should use it like `f: ...`. Use it like `f(...): ...` is always an error I see the example of this in slide 17. it might be OK if it looks better, but still it's not in the spec. please open an issue if we think this is OK. [22:11:24.0570] * I see the example of this in slide 17. it might be OK if it looks better, but still, it's not in the spec. please open an issue if we think this is OK and I'll add it into the spec. [09:20:56.0414] Oh, that's definitely been explicitly discussed in the past. [09:21:28.0264] But hm, I'm probably fine with restricting it. [10:10:12.0169] > <@ljharb:matrix.org> i'd love more elaboration on slide 17 also What sort of elaboration are you thinking of? In the slide itself (there's not really much space) or just in speaker notes? [10:10:55.0287] like "matches" and "doesn't match", i'm pretty confused about why some of those are [10:44:41.0737] Okay, I've addressed all of the feedback. [10:45:03.0327] ljharb: I've rewritten slide 17 a decent bit, is it clearer or do you still want more details in the notes? [10:46:38.0120] Now let me go rewrite the README, it's so inconsistent with both itself and the spec text proposal [10:57:46.0236] so why does `Option.Some` match 5, but `Option.some()` does not? [10:58:25.0758] also, in the second example, what happens with `Option.None(undefined)`? is that different than `Option.None()`? [11:02:58.0403] `Option.Some` is doing a boolean check - per the impl, it just verifies the type is right. Option.Some() is doing a list check - the impl returns a `[s.v]` array, and the arglist (equivalent to a `[]` matcher) doesn't match it. [11:04:03.0361] Similarly, `Option.None(undefined)` wouldn't match, because the impl returns a `[]` value, which doesn't match a `[undefined]` pattern. [11:24:11.0768] * `Option.Some` is doing a boolean check - per the impl, it just verifies the type is right (which is the expected pattern for most custom matchers in boolean context). Option.Some() is doing a list check - the impl returns a `[s.v]` array, and the arglist (equivalent to a `[]` matcher) doesn't match it. [12:41:14.0694] Slide 4: use of `-` as separator in > 0/+0/-0 only exception - 0 compares with SameValueZero Is mildly confusing as it could be read as `-0`. I suggest changing this to an em-dash or using `:` [12:44:15.0193] > <@ljharb:matrix.org> originally we had `undefined`, `Infinity`, and `NaN` as "special", where they'd never be identifiers and always refer to the intuitive values I'm not a fan of changing scoping semantics to be out of line from the rest of the language as it breaks intuition in other ways and prevents host emulation (i.e., what if someone wants to create a `Compartment` that replaces the global `Infinity` or `NaN` in some fashion). [12:46:12.0157] aha ok thanks [12:46:41.0981] i think that's a weirdness of extractors then, that only adding `()` drastically changes the meaning of the pattern, but i suppose it's true in JS too [12:50:24.0266] Not a weirdness, IMO. To extract you must have something to destructure and match against. `foo is Bar()` would expect the custom match result to yield zero elements, so `true` is not a reasonable result to match against. [12:54:12.0558] TabAtkins: I'd recommend you move custom matcher slides closer to the end so that we don't end up stuck on that topic before we've provided context about the rest of the pattern syntax and matching behavior. If you want to reference how `match (x) { Number: ... }` works, I'd do it in a more hand-wavy way and just say that we'll come back to that later in the slides. [13:06:33.0165] IMO, a good topic order for these slides might be: 1. `match` syntax overview 2. Literal constant patterns (i.e., "Primitive Patterns") 3. Reference patterns (variable references and member references) 4. Object patterns 5. Array patterns 6. Discards/`void` patterns 7. Extractors 9. Combinator patterns (and/or/not/parens) 8. Variable declaration patterns (i.e., `let`/`const`/`var`) - calling them "Binding Patterns" is mildly confusing as JS already has something else called a binding pattern 10. `if` patterns 11. Semantics of custom matchers 12. Future syntax This order progressively builds in complexity while leveraging key information from previous slides. For example `if` patterns really need `and` to be meaningful. Oftentimes, so do `let` patterns. [13:09:25.0920] On slide 20, you have `match (Option.Some(5))` and `match (Option.None())`. Since you have defined these as `class` definitions, these examples would throw at runtime. They should read `match (new Option.Some(5))` and `match (new Option.None())`. the latter of which is somewhat unfortunate since you only really want a singleton instance of `None`. [13:13:51.0956] Also, the definition itself throws at runtime because you don't call `super()`. [13:14:07.0890] > <@rbuckton:matrix.org> IMO, a good topic order for these slides might be: > 1. `match` syntax overview > 2. Literal constant patterns (i.e., "Primitive Patterns") > 3. Reference patterns (variable references and member references) > 4. Object patterns > 5. Array patterns > 6. Discards/`void` patterns > 7. Extractors > 9. Combinator patterns (and/or/not/parens) > 8. Variable declaration patterns (i.e., `let`/`const`/`var`) - calling them "Binding Patterns" is mildly confusing as JS already has something else called a binding pattern > 10. `if` patterns > 11. Semantics of custom matchers > 12. Future syntax > > This order progressively builds in complexity while leveraging key information from previous slides. For example `if` patterns really need `and` to be meaningful. Oftentimes, so do `let` patterns. Makes sense, especially since the current custom matcher slides end up having to care about the extractor details too. [13:16:36.0732] Tho I think variable declarations needs to be earlier; I need them in several other examples. I think the use of combinators is obvious enough to use them ahead of time without comment. [13:20:40.0953] Here's another way to write `Option`: ```js class Option { static #none = new this(); #value; constructor(value) { this.#value = value; } static Some(value) { return new Option(value); } static None() { return Option.#none; } static { this.Some[Symbol.customMatcher] = function (s, hint) { if (s && #value in s && s !== Option.#none) { return hint === "boolean" ? true : [s.#value]; } return false; }; this.None[Symbol.customMatcher] = function (s, hint) { if (s === Option.#none) { return hint === "boolean" ? true : []; } return false; }; } } ``` [13:22:36.0089] * Here's another way to write `Option`: ```js class Option { static #none = new this(); #value; constructor(value) { this.#value = value; } static Some(value) { return new Option(value); } static None() { return Option.#none; } static { this.Some[Symbol.customMatcher] = function (s, hint) { if (s && #value in s && s !== Option.#none) { return hint === "boolean" ? true : [s.#value]; } return false; }; this.None[Symbol.customMatcher] = function (s, hint) { if (s === Option.#none) { return hint === "boolean" ? true : []; } return false; }; } } ``` [13:24:04.0569] * Here's another way to write `Option` that lets you avoid having to write `new` in the `match` examples: ```js class Option { static #none = new this(); #value; constructor(value) { this.#value = value; } static Some(value) { return new Option(value); } static None() { return Option.#none; } static { this.Some[Symbol.customMatcher] = function (s, hint) { if (s && #value in s && s !== Option.#none) { return hint === "boolean" ? true : [s.#value]; } return false; }; this.None[Symbol.customMatcher] = function (s, hint) { if (s === Option.#none) { return hint === "boolean" ? true : []; } return false; }; } } ``` [13:29:33.0432] I think you should rename the "Variable Patterns" slide. You're using "Variable" here while talking about an `IdentifierReference`, while I'd more equate "Variable" to `let`/`const`/`var` patterns [13:30:45.0099] IMO, "Reference Patterns" is probably a more correct description for the audience since it involves multiple things that produce the `Reference Record` specification type (identifier references and property references) [13:42:37.0978] In slide 17 you say "specified length", which might be conflated with `array.length`. I'd suggest you either use "same number of elements" and "match the corresponding elements" or something to the effect of "Matches if the sub-patterns match corresponding elements in the subject, with no more and no fewer elements". [13:45:06.0650] In slide 18, you say "Not strict" but I think "Not exhaustive" might be better given that "strict" has other connotations in JS. [13:47:05.0199] Also, as mentioned above, in slide 19 "Extractor Patterns", `true` is not the same as `[]`. Honestly I'd rather a custom matcher throw if you use it as an extractor and it wasn't written to be used in that fashion. [13:49:32.0684] On Slide 21 "Caching of Subject Parts", you have "Object patterns similar cache". I think you meant "similarly", but I would just remove the word altogether. [13:52:01.0615] > <@tabatkins:matrix.org> Makes sense, especially since the current custom matcher slides end up having to care about the extractor details too. thinking about it, you mention combinators when talking about caching. It might be better to move combinators up before object and array patterns since you can use examples like `"apple" or "banana"` without needing to dig into other complexity. [13:56:46.0087] For example, you can describe `or` in simply with `"apple" or "banana"`, `not` simply with `not String`, and `and` simply by building on `not`: `String and not "apple"` [13:56:57.0786] * For example, you can describe `or` simply with `"apple" or "banana"`, `not` simply with `not String`, and `and` simply by building on `not`: `String and not "apple"` [13:57:08.0195] * For example, you can describe `or` simply with `"apple" or "banana"`, `not` simply with `not String`, and `and` simply by building on `not` with `String and not "apple"` [14:00:00.0003] We may also want to describe `or`, `and`, and `not` as "Disjunction", "Conjunction", and "Negation" patterns, but that's my personal preference. [14:00:17.0613] And "Parentheses" as "Grouping Patterns" [14:01:21.0855] Also, "Comparison Patterns" might be more aptly described as "Relational Patterns" as they mostly cover relational expressions and that is what is often used as the terminology in prior art. [14:07:55.0291] In "Compact Object Pattern Cases", I'm not bullish on `{ a }` as meaning "equivalent to `{ a: void }`" as that would break from how shorthand assignments work in object literals, assignment patterns, and binding patterns. One might expect `{ a }` to mean `{ a: a }`, just as `{ let a }` means `{ a: let a }`. It may not be convenient, but it would be consistent. [14:08:05.0637] * In "Compact Object Pattern Cases", I'm not bullish on `{ a }` meaning "equivalent to `{ a: void }`" as that would break from how shorthand assignments work in object literals, assignment patterns, and binding patterns. One might expect `{ a }` to mean `{ a: a }`, just as `{ let a }` means `{ a: let a }`. It may not be convenient, but it would be consistent. [14:25:19.0650] > <@rbuckton:matrix.org> I'm not a fan of changing scoping semantics to be out of line from the rest of the language as it breaks intuition in other ways and prevents host emulation (i.e., what if someone wants to create a `Compartment` that replaces the global `Infinity` or `NaN` in some fashion). anybody who wants to change the meaning of those things is a bad person and should feel bad [14:26:27.0735] like i can't even conceive of a valid use case for it [14:28:20.0481] Maybe so, but we still shouldn't break lexical scoping behavior for one feature, that just makes things more complex and a source of confusion for users. If its a bad enough problem that it needs fixing, we should find a way to fix it consistently. [14:28:59.0277] in general i'm in favor of consistency, but just like with coercion, and a number of other things, we shouldn't keep making new things bad just because we can't fix the existing badness [14:29:44.0959] it would make things more complex for engines and tooling, surely. but i do not believe it'd confuse anyone [14:30:26.0621] * it would make things more complex for engines and tooling, surely. but i do not believe it'd confuse anyone (the ability to redefine them is what's confusing) [14:30:35.0830] This one seems like borrowing trouble. If no one is shadowing `undefined`, `Infinity`, and `NaN` today because its a bad practice, then fixing this here does nothing. If people are shadowing those things, then shame on them for doing that and we shouldn't go out of our way to fix it for that narrow case. [14:31:50.0287] If they're shadowing for a reason, then don't break that reasoning. If they're shadowing by mistake, then they will likely have other problems besides `match`. Its just not worth borrowing trouble, IMO. [14:32:08.0605] it's not just about them tho [14:32:24.0562] basically every application runs third-party code. that code could mistakenly or intentionally redefine those things. [14:33:13.0685] that's more of an argument for sandboxing and `Compartment` than it is for changing behavior here. [14:39:26.0300] We could always investigate specifying `undefined`, `Infinity`, and `NaN` as immutable globals. No package that redeclares them with a value that isn't the original value is likely to be doing anything good. That would address the global concern, and third party code can't shadow a global in your own code, aside from `eval`. [14:40:59.0489] true 2024-09-26 [13:59:46.0037] I [14:00:23.0721] I'd appreciate if someone can take a quick look over https://github.com/tc39/proposal-extractors/pull/29 before I merge. I'd like to get the extractors spec updated before the agenda deadline. 2024-09-27 [00:09:18.0928] > <@rbuckton:matrix.org> IMO, a good topic order for these slides might be: > 1. `match` syntax overview > 2. Literal constant patterns (i.e., "Primitive Patterns") > 3. Reference patterns (variable references and member references) > 4. Object patterns > 5. Array patterns > 6. Discards/`void` patterns > 7. Extractors > 9. Combinator patterns (and/or/not/parens) > 8. Variable declaration patterns (i.e., `let`/`const`/`var`) - calling them "Binding Patterns" is mildly confusing as JS already has something else called a binding pattern > 10. `if` patterns > 11. Semantics of custom matchers > 12. Future syntax > > This order progressively builds in complexity while leveraging key information from previous slides. For example `if` patterns really need `and` to be meaningful. Oftentimes, so do `let` patterns. I'll update the spec to rename the term "BindingPattern" to what you suggested [00:12:32.0428] > <@rbuckton:matrix.org> Also, as mentioned above, in slide 19 "Extractor Patterns", `true` is not the same as `[]`. Honestly I'd rather a custom matcher throw if you use it as an extractor and it wasn't written to be used in that fashion. Yes, built-in custom matchers has an AO for this. ValidateCustomMatcherHint [00:14:42.0729] > <@rbuckton:matrix.org> We may also want to describe `or`, `and`, and `not` as "Disjunction", "Conjunction", and "Negation" patterns, but that's my personal preference. this name is better imo, but it's 3 names and we only use one term in the spec "CombinedMatchPattern", do you have suggestion? [00:26:26.0869] > <@rbuckton:matrix.org> In "Compact Object Pattern Cases", I'm not bullish on `{ a }` as meaning "equivalent to `{ a: void }`" as that would break from how shorthand assignments work in object literals, assignment patterns, and binding patterns. One might expect `{ a }` to mean `{ a: a }`, just as `{ let a }` means `{ a: let a }`. It may not be convenient, but it would be consistent. pattern `{ a }` is already an early error in the spec due to the possible confusion. [00:26:50.0281] * pattern `{ a }` is already an early error in the spec due to the possible confusion. https://tc39.es/proposal-pattern-matching/#sec-match-patterns-static-semantics-early-errors [08:35:07.0325] > <@jackworks:matrix.org> pattern `{ a }` is already an early error in the spec due to the possible confusion. > https://tc39.es/proposal-pattern-matching/#sec-match-patterns-static-semantics-early-errors These were all comments related to the slides [14:34:08.0687] I've posted the slides for Extractors in case anyone has feedback: https://1drv.ms/p/s!AjgWTO11Fk-Tkr0Z2sm9bVmO_agqpA?e=7TdVup [14:34:29.0917] I've kept in some of the slides from previous meetings as hidden slides at the end of the deck in case I need to dig something up during discussions. 2024-09-29 [05:58:41.0821] > <@rbuckton:matrix.org> I've posted the slides for Extractors in case anyone has feedback: https://1drv.ms/p/s!AjgWTO11Fk-Tkr0Z2sm9bVmO_agqpA?e=7TdVup you can copy Function.prototype [ %Symbol.customMatcher% ] to extractor proposal maybe https://tc39.es/proposal-pattern-matching/#sec-function.prototype-%symbol.custommatcher% [08:53:47.0441] That won't be very useful for the extractors proposal because binding/assignment patterns need an iterable result [08:56:04.0004] with this, you can write a normal function and call it in the example without implement it as { [Symbol.customMatcher]: ... } [10:59:16.0457] Perhaps, but I'm trying to illustrate the API itself. Besides, that will be covered in the pattern matching slides 2024-09-30 [07:54:20.0247] Are we meeting today? [08:08:09.0352] I'm in the meeting but don't know if we have agenda [08:09:59.0761] Only Jack Works and I seem to be in attendance, so I am assuming this meeting is cancelled for today. We've been fairly hit or miss (mostly miss) for this meeting for months. Do we need to find a new day/time or meeting frequency that is more conducive to everyone's schedules? [08:10:50.0821] or do we need an agenda so shakeholders know they need to attend