| 01:06 | <nicolo-ribaudo> | Chairs, is the decorators update still happening? I believe that there is new information that would be great for the committee to hear, even if Jacob is not here |
| 01:13 | <Aki> | Reminder that if you presented, you need a summary of the presentation/conversation, and to record any conclusions that were reached. Here's some ongoing tracking https://kdrive.infomaniak.com/app/office/1777368/13 |
| 01:14 | <waldemar> | What's the "Unable to load event that was replied to, it either does not exist or you do not have permission to view it." that this is replying to? |
| 01:15 | <bakkot> | https://matrixlogs.bakkot.com/TC39_Delegates/2025-11-19#L525 |
| 01:15 | <bakkot> |
|
| 01:15 | <Chris de Almeida> | hmmm.. with the continuations we have, the schedule is now full again. but we could do it if time allows |
| 01:16 | <nicolo-ribaudo> | Nevermind, I misunderstood and there is much less information at the moment that what I was thinking, sorry 😅 |
| 01:19 | <Chengzhong Wu> | |
| 01:22 | <Chengzhong Wu> | maybe the topic should be moved to the overflown section, instead of being "discussed" yesterday |
| 01:30 | <Rob Palmer> | For Decorators, is there anyone who would like to volunteer to lead the discussion in the likely case that Jacob cannot do it? |
| 01:30 | <nicolo-ribaudo> | I retracted my suggestion to do it anyway, in case you are asking because of my suggestion |
| 01:30 | <waldemar> | Measuring height of person: https://xkcd.com/3164/ |
| 01:58 | <eemeli> | waldemar: Could you coment here on what you would've said with your "disagree" reply? |
| 02:08 | <mgaudet> | (I'm confused. Isn't Watt an SI unit for Power, and Joule for Energy?) |
| 02:14 | <Richard Gibson> | indeed: https://www.bipm.org/documents/20126/41483022/SI-Brochure-9-EN.pdf#page=23 |
| 02:14 | <snek> | kwh is my favorite si unit |
| 02:19 | <waldemar> | The summary included an incorrect assertion that no one wanted an Amount that only does precision with no units. That's what I disagreed with. |
| 02:20 | <waldemar> | I had earlier stated in the conversation that I would support such a thing. |
| 02:20 | <eemeli> | Would you prefer an Amount that initially did not support unit conversion? |
| 02:21 | <Rob Palmer> | "Paving desire paths" - making existing usage easier and robust |
| 02:21 | <waldemar> | Precision of a decimal number and unit conversion are two very different things. There are plentiful use cases of one without the other. |
| 02:23 | <waldemar> | There exist use cases for both simultaneously, but that doesn't mean that all decimal number precision should be tied to unit conversions and vice versa. |
| 02:23 | <rkirsling> | https://www.w3.org/TR/html-design-principles/#pave-the-cowpaths |
| 02:24 | <Olivier Flückiger> | Relatedly, do we have some connection to stateofjs? |
| 02:25 | <eemeli> | I agree. Do I understand right that you would not be opposed to an initial Amount that also supported unit conversion, provided that we find agreement on the details thereof? |
| 02:25 | <ljharb> | i think the survey owner is in the general channel |
| 02:27 | <bakkot> | not afaik but the person usually solicitcs feedback in #tc39-general:matrix.org before launching |
| 02:28 | <keith_miller> | Olivier Flückiger: Does V8 cache the result of the internal equivalent to getNonIndexStringProperties? |
| 02:29 | <Olivier Flückiger> | Ok, just came to mind re. "surveys are hard". We noticed that in the "pick 3 items" sections the distribution follows almost exactly the order of questions asked. |
| 02:29 | <Olivier Flückiger> | No, we cache a list of enumerable properties in the order of enumeration. |
| 02:30 | <keith_miller> | I have some concerns that each of the new getXYZPropreties will be expected to be cached but that will induce memory overhead in all cases without non-trivial effort |
| 02:31 | <keith_miller> | Is that a concern that other engines share? It's not super strong opinion FWIW |
| 02:32 | <keith_miller> | I also don't necessarily mean the actual cached data itself I mean the pointer to the possibly cached data |
| 02:32 | <Olivier Flückiger> | Yeah, that is a good point. We would not plan to add a cache. I recently added a fast-path for getOwnPropertySymbols without a cache. That gave about 30% speedup, but same copmlexity class. |
| 02:32 | <Olivier Flückiger> | But I think anything else than enumeration would not be critical enough to warrant a cache |
| 02:33 | <nicolo-ribaudo> | If this is not cached and requires iterating through the properties, is it actually going to be meaningfully faster than iterating in JS? |
| 02:34 | <Olivier Flückiger> | Well, same as with counting keys, we would not create the keys array. |
| 02:34 | <Olivier Flückiger> | and also no regex, but an internal test. |
| 02:35 | <mgaudet> | I think it would be faster for us, because we can just walk a shape-lineage |
| 02:35 | <Christian Ulbrich> | In https://github.com/BridgeAR/array-get-non-index-string-properties I do not see any real use case. We are now talking about "errors", "logging", there is no mentioning of "logging" neither "errors" on the proposal so far. |
| 02:35 | <James M Snell> | Node.js' use of this doesn't require caching. I wouldn't expect that at all |
| 02:36 | <ljharb> | fwiw console.log is a universal use case for exactly "describing every kind of thing", and the committee spent a TON of effort in ES6 trying to make web behavior implementable in JS |
| 02:37 | <jkup> | I do think it's interesting hearing from Jordan/Mathieu/Ruben on use cases but the current examples on the proposal repo itself seem a bit contentious to me |
| 02:39 | <keith_miller> | Aren't they different big-O with the caching? I don't think one can say either way. |
| 02:40 | <keith_miller> | As in if you have 1M indexed properties and one named property, even with caching that's gonna be slower than this. But if you have 1 indexed property and 1M named properties the cached array is going to be faster in JS |
| 02:41 | <snek> | what if property descriptors had boolean getters telling you all the different categories and whether the property fit that category |
| 02:43 | <nicolo-ribaudo> | Also, does this actually requires a regexp when running in userland? Or can it do String(Number(d)) === d && d|0 === Number(d)? |
| 02:43 | <rbuckton> | Internal descriptors or JS materialized descriptors? materializing a JS descriptor for that case seems fairly expensive. Why not just a isIntegerIndexKey(text) that does the complex test against a key name? |
| 02:43 | <nicolo-ribaudo> | And could it use for-in to avoid allocating the keys array? |
| 02:43 | <snek> | materialized js descriptors. could also be %PropertyDescriptorPrototype% :> |
| 02:44 | <Christian Ulbrich> | Ruben: I think, would really help here, if there are actual use cases, either in some existing packages or at least in a way of some pseudo-code that would give me more perspective on, what you are trying to solve. For me this is a different language mechanisms like Object.entries for example. But feel free to ask me off plenary about that. |
| 02:44 | <snek> | the logging case needs property descriptors anyway so idk if the overhead would actually be that much in practice |
| 02:45 | <Olivier Flückiger> | Getting descriptors is not super fast. Pretty big allocation and unrelated information. |
| 02:45 | <nicolo-ribaudo> | I think this is about having a fast-path to not get descriptors when the TA is not weird |
| 02:45 | <Olivier Flückiger> | Since what you get as the descriptor datastructure is not what the engines will have internally. |
| 02:46 | <ljharb> | logging doesn't always need descriptors |
| 02:46 | <Olivier Flückiger> | However all of these discussions make me wonder if there would be an alternative proposal route that involves giving a more performance oriented api to descriptors. |
| 02:46 | <ljharb> | the existence of keys is typically the most valuable information, not a key's enumerability or configurability etc |
| 02:47 | <snek> | its just very likely in e.g. node's logger that a property descriptor will be materialized for any (non-exotic) properties |
| 02:47 | <waldemar> | That's correct. My worry is about the complexity and details of combining them, but if we can figure that out, that would be a fine outcome. |
| 02:51 | <rkirsling> | uhh wait |
| 02:51 | <rkirsling> | doesn't that mean it should be retroactively lowered to 2.7? |
| 02:51 | <rkirsling> | should I put that on queue |
| 02:52 | <nicolo-ribaudo> | I have replies if it gets on the queue |
| 02:56 | <Rob Palmer> | I agree with keeping Decorators at Stage 3 to reflect the main message that this proposal is in the implementation phase. TS shipped a while ago. We've done a few stage regressions for much more meaningful reasons. |
| 02:56 | <Justin Ridgewell> | Are any implementers actually excited for this feature? |
| 02:56 | <Justin Ridgewell> | Are any delegates? |
| 02:57 | <Mathieu Hofman> | I would love this feature |
| 02:57 | <Justin Ridgewell> | I’m certainly not… |
| 02:57 | <snek> | i'm excited for decorators on bare functions |
| 02:57 | <rkirsling> | this feature only scares me, if I'm honest |
| 02:57 | <Mathieu Hofman> | I definitely would like decorators on bare functions, possibly on bindings too |
| 02:57 | <rbuckton> | A fair amount of the developer community is. |
| 02:57 | <Mathieu Hofman> | more than classes TBH |
| 02:57 | <Chengzhong Wu> | would this be a kind of implementation feedback, which counts for stage 3 feedback? |
| 02:57 | <Chris de Almeida> | browser vendors be like |
| 02:58 | <Justin Ridgewell> | Yes. But I think we’re getting that feedback now. |
| 02:59 | <James M Snell> | Server runtime implementors be like... |
| 02:59 | <Justin Ridgewell> | I think Frameworks shipping this was a huge mistake, and that’s now influenced the users of those frameworks. |
| 02:59 | <Rob Palmer> | There is a bunch of folk in Node ecosystem waiting for decorators. |
| 02:59 | <Christian Ulbrich> | While of course decorators depend on your preference for meta-programming or not, those that do meta-programming are really yearning for this feature! |
| 03:00 | <Christian Ulbrich> | They are used in quite some big frameworks for that matter. |
| 03:00 | <Justin Ridgewell> | I particularlly hate Java annotations, and this is exactly the same meta programming that makes the codebase impossible to reason about. |
| 03:00 | <bakkot> | I do lots of meta programming and am the opposite of yearning for this feature |
| 03:01 | <Christian Ulbrich> | Justin Ridgewell: With great power comes, great responsibility, but I'd rather use power wisingly, than having no power at all. |
| 03:01 | <snek> | society if meme for if v8 had accepted the edge and deno plan to ship decorators |
| 03:01 | <Justin Ridgewell> | Great power hides the massive performance impact this’ll have on classes. |
| 03:01 | <Ashley Claymore> | I find the JS decorators proposal very different to Java annotations |
| 03:02 | <snek> | james is typing but he's not even at his computer, incredible |
| 03:02 | Chengzhong Wu | is typing |
| 03:02 | <Christian Ulbrich> | You can do so much more, than meta-programming with them! I for example use them as tagging decorators (basically Java's) annotation, i.e. those are decorators that have no function body, you can use them to get them easily in the AST. |
| 03:03 | <Ashley Claymore> | JS Decorators are functions that you can jump to like any function call and see what it does. Java Decorators were not like that at all |
| 03:03 | <Christian Ulbrich> | Justin Ridgewell: Proxies also have performance implications, yet teams decide to use them, for better maintainability / clearer architecture / etc. |
| 03:04 | <Chris de Almeida> | I was just complaining about this sort of Java 'magic' to Lea last night |
| 03:04 | <Christian Ulbrich> | Ashley Claymore: I know that Java annotations are laughable, but with JS decorators of course you can do the same thing. |
| 03:04 | <Ashley Claymore> | absolutely |
| 03:05 | <Ashley Claymore> | people can always do bad things |
| 03:05 | <rbuckton> | If you looked at Decorators as used in TypeScript/Babel as an experiment, they are a proven success in the ecosystem. They reduce boilerplate and open up numerous possibilities that often reduce the need for new syntax proposals |
| 03:26 | <Jake Archibald> | If anyone's interested, here's the bit of the observables design that I found particularly surprising https://github.com/WICG/observable/issues/216. Seems like I'm not the only one? |
| 03:28 | <Aki> | Reminder to add your summaries and conclusions to the notes. And links to proposals/PRs/slides if they're missing. |
| 03:29 | <jkup> | thank you for writing this up, I think this is extremely surprising too |
| 03:57 | <Chris de Almeida> | it puts the summary and conclusion in the doc or else it gets Aki's wrath again |
| 04:09 | <Aki> | Ecma language spotted! |
| 04:11 | <Jack Works> | hello spec writers I'm here to sell my ecmarkup language service extension, have a try! It provides code highlight, completion, go to definition, etc... https://marketplace.visualstudio.com/items?itemName=MagicWorks.ecmarkup |
| 04:11 | <Christian Ulbrich> | Without having looked at the Babel example, I bet it that a class is used as a namespace, this is a valid pattern and we will never get rid of it, by not enabling future class composition features. |
| 04:12 | <rbuckton> | "really big anything" is an antipattern, but at some point the rubber hits the road and you end up with big classes or big modules or big functions. |
| 04:13 | <ljharb> | nicolo-ribaudo: wouldn't "having a separate class for comparison stuff", for example, make it easier for users to find things too, as well as babel maintainers? |
| 04:13 | <bakkot> | classes as a bag of extension points often need to be large |
| 04:13 | <nicolo-ribaudo> | Well then you need to create that class. That class that was on screen is kind of like Node on the web, which has a bunch of utilities all for dealing with nodes |
| 04:14 | <bakkot> | like we have https://github.com/shapesecurity/shift-reducer-js/blob/es2019/gen/monoidal-reducer.js |
| 04:14 | <bakkot> | with, what, 99 method? |
| 04:14 | <nicolo-ribaudo> | The plugin author is handled one thing that contains all the utilities on its prototype |
| 04:14 | <bakkot> | but consumers just have like 4 or 5 https://github.com/shapesecurity/shift-reducer-js/blob/es2019/examples/contains-this.js |
| 04:15 | <rbuckton> | At one point I was considering proposing something like partial class to JS as a more standardized way of patching/augmenting existing classes w/o resorting to manual prototype patching. |
| 04:15 | <Justin Ridgewell> | If only we had pipeline and module-level functions… |
| 04:16 | <rbuckton> | In TS you could always reopen the static side of a class with namespace. Reopening the instance side of a class required an interface augmentation and prototype patching, unfortunately. |
| 04:17 | <rbuckton> | It's possible to emulate multiple inheritance in JS using Proxy but its very slow. |
| 04:17 | <Michael Ficarra> | Haskell type classes are just Rust traits but with a better type system (HKTs) |
| 04:19 | <Ashley Claymore> | Not saying I agree with everything, but I found this talk really interesting: https://youtu.be/Gz7Or9C0TpM |
| 04:19 | <Michael Ficarra> | I think Haskell also allows orphan instances but you shouldn't do that |
| 04:19 | <Ashley Claymore> | lots in relation to this |
| 04:20 | <Ashley Claymore> | the talk covers their current direction for handling ambiguity/clashes when extending a type |
| 04:20 | <Chris de Almeida> | this is awesome 👏👏👏 |
| 04:21 | <ljharb> | +1, i use it |
| 04:21 | <rbuckton> | I wish I'd had more time to keep working on my ecmarkup extension :( |
| 04:22 | <ljharb> | fwiw i am strongly anti-interested in using web components as a design inspiration for anything |
| 04:22 | <nicolo-ribaudo> | This "custom form controls" example could be done with decorators too |
| 04:22 | <nicolo-ribaudo> | With a class decorator |
| 04:23 | <rbuckton> | I think that might have been the original idea. There was a lot of interest in decorators from the web components authors years ago. It informed some of the design of the proposal, including .addInitializer, IIRC |
| 04:24 | <snek> | you know traits.js is good because it has a download button |
| 04:38 | <danielrosenwasser> | I removed myself from the queue because I'm afraid we are running out of time |
| 04:40 | <nicolo-ribaudo> | We don't adopt it right? |
| 04:40 | <nicolo-ribaudo> | Some of us do |
| 04:40 | <nicolo-ribaudo> | But not as a committee |
| 04:40 | <danielrosenwasser> | (just clarifying that I'm not trying to abuse the queue to throw a point out) |
| 04:40 | <rkirsling> | oh man a third overload for PoC |
| 04:43 | <mgaudet> | I don't really understand the 'stateful sub-instance' phrase -- does anyone have a definition? |
| 04:48 | <mgaudet> | (There's so much confusion caused by talking about prototypical inheritance vs. C++ style/Java style inheritance) |
| 04:48 | <mgaudet> | (and class doesn't help alas) |
| 04:48 | <snek> | prototypial or prototypical 👀 |
| 04:49 | <mgaudet> | erm. |
| 04:49 | <mgaudet> | yes |
| 04:49 | <ljharb> | prototypal? |
| 04:49 | <rbuckton> | prototypal |
| 04:49 | <rbuckton> | what ljharb said |
| 04:49 | <nicolo-ribaudo> | My proto-pal |
| 04:49 | <snek> | yeah typo'd that |
| 04:49 | <rkirsling> | prototypo |
| 04:50 | <rbuckton> | is prototypal/prototypial like aluminum/aluminium? |
| 04:50 | <Michael Ficarra> | 👮 take it to TDZ! |
| 04:55 | <Michael Ficarra> | the tightly-coupled use cases are not all that motivated IMO, the whole value is in the loosely-coupled use cases |
| 04:56 | <Christian Ulbrich> | As I have said, if somebody is interested in composition of MixIns with CustomElements then give me a shoutout. Have a <make-blinking> structural mixin that you can compose with any CustomElement to make it blink. 😀 |
| 04:58 | <bakkot> | sidebar: we need https://github.com/tc39/proposal-private-declarations |
| 04:58 | <bakkot> | this is the only syntax proposal I think we actually need in the language |
| 04:58 | <bakkot> | well, this and module declarations |
| 04:58 | <bakkot> | notably, neither of those are just sugar |
| 05:00 | <Chengzhong Wu> | isn't module declarations a sugar for multi-file modules? |
| 05:01 | <rbuckton> | Alternatively,
|
| 05:02 | <ljharb> | oof, i wish that had been posted in tdz |
| 05:02 | <snek> | i can imagine implementations would love geti |
| 05:02 | <rbuckton> | plus Symbol.geti could work with Index and Range objects as first class ^1 and 0:1 for index-from-end and slice/splice syntax |
| 05:03 | <bakkot> | no, because multi-file modules have other observable effects (network access, e.g.), and you can't use them from a script such as an inline script |
| 05:03 | <ljharb> | you can do it with blob modules :-p |
| 05:04 | <snek> | mlobules |
| 05:04 | <rkirsling> | blobules |
| 05:04 | <bakkot> | nope, blob modules are still considered network access from the point of view of CSP |
| 05:04 | <ljharb> | oh weird |
| 05:07 | <bakkot> | they kind of have to be either network access or eval for CSP to work at all |
| 05:07 | <bakkot> | (possibly they should have been considered eval, but either way, same problem here) |
| 05:07 | <ljharb> | ah true, they're more like eval than network imo but either way |
| 05:09 | <rbuckton> | This is potentially an example of how a decorator could accomplish the same thing as new syntax:
Not that I'm opposed to the syntax, per se, but decorators would allow for experimentation with this idea in userland before adoption as syntax. |
| 05:09 | <ljharb> | a useful read (or reread) for folks here might be https://legacy.reactjs.org/blog/2016/07/13/mixins-considered-harmful.html |
| 05:10 | <Christian Ulbrich> | React is the site, that teaches you, that classes are hard to reason about, for machine and computers, so take that in consideration before reading that... |
| 05:10 | <jkup> | having flight.js flashbacks |
| 05:11 | <Satish> | How to specify Symbol.iterator methods in classes? For example, like what we can do with array literals,
|
| 05:11 | <ljharb> | the same way (like, precisely the same syntax as concise object methods) |
| 05:11 | <Christian Ulbrich> | React is also the framework, that had stateless function components, before they changed them to functional components. |
| 05:11 | <ljharb> | (they're still stateless tho, useState isn't actually storing state on the component) |
| 05:11 | <snek> | according to a quick google search, react is also considered harmful |
| 05:12 | <ljharb> | note i suggested reading the article, not just the headline :-p |
| 05:14 | <Michael Ficarra> | just because something's possible doesn't mean it should be encouraged |
| 05:15 | <rbuckton> | I think I'd rather have something like class Foo extends Bar, Baz { } than class Foo extends Bar { ...Baz } |
| 05:15 | <ljharb> | not that i want either one of them, but i agree on the relative preference there |
| 05:16 | <Christian Ulbrich> | JS is multi-paradigm. It brings many tools to the table. Not all of them are equally "encouraged, everywhere, at once". |
| 05:16 | <Ashley Claymore> | some are less encouraged than others tho |
| 05:17 | <Christian Ulbrich> | Even without progressing the language any tiny bit further, you can build the very worst things, (wo)mankind can think of in terms of software design. |
| 05:17 | <rbuckton> | IMO, multi-argument extends would be sufficient for anything from multiple inheritance to mixins to protocols |
| 05:18 | <rbuckton> | Especially considering it's already somewhat feasible with a helper, e.g. class Foo extends f(Bar, Baz) {} |
| 05:19 | <snek> | what does f do there |
| 05:19 | <snek> | return a proxy? |
| 05:19 | <snek> | or do composition |
| 05:19 | <Christian Ulbrich> | Mixins are a reality. |
| 05:19 | <rbuckton> | I used f as a placeholder. It could be mixin(...) or something else, it doesn't matter. |
| 05:19 | <Michael Ficarra> | megamorphic functions will always be slow @ljharb, that's not gonna change |
| 05:20 | <ljharb> | so is eval. doesn't mean we should encourage it. |
| 05:20 | <rbuckton> | Some implementation of f could theoretically do any of those operations depending on the input it receives. |
| 05:22 | <Christian Ulbrich> | ljharb: eval() is a core feature of the language and it is - to me - something that every "interpreted" language has. It has the power to do everything, if you want to have a language, that disallows (i.e. "not encourage") things, go for a DSL that is non-turing-complete. |
| 05:22 | <ljharb> | sure, i'm not saying we shouldn't have it. i'm saying we shouldn't add affordances that encourages its increased use |
| 05:23 | <ljharb> | which is 1000% the case for mixins imo. it exists but it's bad and we shouldn't make it easier to do |
| 05:23 | <Christian Ulbrich> | Mixin or NotMixin is not a thing, a language, we as a multi-paradigm language should be encouraging / disencouraging. |
| 05:24 | <Michael Ficarra> | hard disagree @Christian Ulbrich |
| 05:24 | <ljharb> | that is entirely part of our job |
| 05:24 | <Christian Ulbrich> | Michael Ficarra: On what? Mixins specifically? |
| 05:25 | <Michael Ficarra> | all sorts of things are bad and we should be giving them better ways to do things to avoid doing the bad things |
| 05:25 | <ljharb> | people shouldn't omit semicolons either, and it's absolutely our place to tell them that. and the spec has a section on ASI hazards for that reason |
| 05:25 | <Christian Ulbrich> | Michael Ficarra: I agree. But I think, that there is no consensus on "mixins are bad", I am afraid. |
| 05:25 | <Michael Ficarra> | @Christian Ulbrich I don't need consensus |
| 05:26 | <ljharb> | we need consensus to advance. if mixins aren't considered bad by anyone then mixin features won't advance |
| 05:26 | <ljharb> | this was also made pretty clear i think in the plenary session that introduced the existing mixins proposal, back in 2019 or something |
| 05:26 | <Christian Ulbrich> | Of course it works both ways. |
| 05:26 | <Michael Ficarra> | hold up, I'm gonna pull out my slides that eviscerated the mixins proposal |
| 05:27 | <rbuckton> | mixins fill a gap in JS. I'm not personally opposed to mixins, but they do have a number of flaws. We can either address the flaws or find better way to fill the gap. |
| 05:27 | <rkirsling> | to be clear, this topic is just "freely talking about OOP" as opposed to proposing a specific direction, right |
| 05:27 | <ljharb> | the flaws are intrinsic, and i'm totally open to finding better solutions |
| 05:27 | <Jake Archibald> | For folks interested in changes to AbortController & AbortSignal, I've made a discussion-starter here https://github.com/whatwg/dom/pull/1425 |
| 05:27 | <ljharb> | but i'm pretty sure the problem statement here isn't "let's talk about OOP" |
| 05:27 | <rbuckton> | This is now talking about a specific thing. |
| 05:27 | <Christian Ulbrich> | But still time changes. Mixin usage changes. Whether one has a preference for it or not, with for example - web components based on classes, mixins have become a very common pattern to apply common behavior between them. |
| 05:28 | <ljharb> | web component design is not something that we should be inspired by. that you have to use mixins with them is part of that |
| 05:28 | <rbuckton> | The "let's talk about OOP" was the previous item. both are in the same set of slides though. |
| 05:28 | <rkirsling> | oh what |
| 05:28 | <rkirsling> | I literally had no idea the topic changed |
| 05:28 | <rkirsling> | and wondered why it was already 2:30 |
| 05:29 | <snek> | yeah it wasn't announced |
| 05:29 | <Christian Ulbrich> | Of course not. I gave it just as one example, of increased mixin usage. I am pretty certain - without having any data whatsoever - that mixin usage has increased since 2019 across the eco system. |
| 05:29 | <ljharb> | sure. but if you subtract any WC-related usage i do not think this is true |
| 05:29 | <Ashley Claymore> | it was but briefly |
| 05:29 | <Ashley Claymore> | same presenter and same slide deck made it very smooth |
| 05:30 | <Christian Ulbrich> | ...and we can and should not ignore usage of patterns, idioms in the eco system. It certainly pushed us, to put things in the language. As Promise.withResolvers or Promise.try for that matter. |
| 05:30 | <rbuckton> | IMO, mixins and protocols both fill the same gap and neither are a perfect fit. Protocols feel like explicit interface implementations in C#. Mixins feel like implicit interface implementation in C#. C# warns you if you have a conflict and lets you pick and choose syntactically whether to use the implicit or explicit implementation. |
| 05:31 | <rkirsling> | same deck is fine but when I scrolled quickly through the deck there was no point at which it clearly indicated "and now here is a proposal" |
| 05:31 | <ljharb> | explicit > implicit |
| 05:32 | <Ashley Claymore> | the presented slides are different from the link |
| 05:32 | <Ashley Claymore> | localhost is being presented |
| 05:33 | <rbuckton> | explicit avoids conflicts but is unergonomic. implicit can have conflicts but is extremely ergonomic. I don't believe one is better than the other for every use case. |
| 05:33 | <nicolo-ribaudo> | The protocols proposal is also a solution to this stage 1 problem, right? |
| 05:33 | <ljharb> | that's ok, i do |
| 05:33 | <nicolo-ribaudo> | Which means we already decided that that's the rough solution to this problem |
| 05:33 | <nicolo-ribaudo> | As it's at stage 2 |
| 05:33 | <rkirsling> | an abstract problem statement seems difficult here because it seems like spread is the proposal |
| 05:33 | <Steve Hicks> | I feel like there's something around the fact that it's currently impossible to put something in the body of a class to add a property whose value is not a fixed method body and have it end up on either the prototype or the constructor - only the instance (i.e. field = computeValue() but you can't for example wrap a method directly inline) |
| 05:33 | <snek> | i was curious about this as well |
| 05:33 | <rkirsling> | yeah |
| 05:34 | <Aki> | is there a replacement note-taker for jkup? |
| 05:34 | <rbuckton> | That is what decorators are for |
| 05:34 | <jkup> | I was going to say that as well but wasn't 100% sure |
| 05:34 | <rbuckton> | So its not impossible, its just waiting on implementation and test review |
| 05:36 | <Mathieu Hofman> | yeah I thought there was overlap with class protocols too |
| 05:36 | <Mathieu Hofman> | which means we already allowed multiple similar proposals |
| 05:38 | <hax (HE Shi-Jun)> | I think the motivation is clear. In ruby you can use include to compose somethings into a class easily, in mordern static languages, you have trait/protocol etc. In JS... you have nothing. |
| 05:39 | <rbuckton> | I do like protocols. I use a variant of them all over my @esfx/* packages. I think the ability to define default non-symbolic implementations is also important, however. |
| 05:40 | <ljharb> | i think that's a necessity yes |
| 05:41 | <bakkot> | no :( |
| 05:41 | <bakkot> | that's how you get shared global namespaces |
| 05:41 | <rbuckton> | IMO, if we could find a happy medium between mixins and protocols I think that would be the best solution. |
| 05:41 | <bakkot> | how are the words "shared global namespace" not sufficient in themselves to make you recoil from this concept |
| 05:41 | <snek> | implements EventTarget with strings |
| 05:41 | <ljharb> | methods can be strings, it already exists |
| 05:41 | <Chengzhong Wu> | IIUC, withdrawing proposals like mixin will also need to call for consensus |
| 05:42 | <ljharb> | one possibility that lightly encourages symbols but permits strings:
|
| 05:42 | <Michael Ficarra> | I don't like it, but I think I've come around to being okay not nannying |
| 05:42 | <snek> | i'm actually feeling like this is probably the best approach |
| 05:42 | <snek> | modulo the precise syntax |
| 05:42 | <ljharb> | meaning the user, not the author, decides? |
| 05:43 | <snek> | the consumer decides how it augments their public interface yes |
| 05:43 | <snek> | i guess there are conflicting needs pulling in both directions here |
| 05:44 | <snek> | but i think the producer deciding is distinctly more class-inheritence like |
| 05:44 | <Justin Ridgewell> | That seems nice. Or if a conflict is found during mixing, throw an error |
| 05:44 | <snek> | deferring to something else vs saying you fulfill a certain contract |
| 05:44 | <Justin Ridgewell> | I’d prefer to use string names if possible, and use symbols when there’s a conflict |
| 05:44 | <Michael Ficarra> | definitely conflicts would need to be loud |
| 05:44 | <Justin Ridgewell> | Yes |
| 05:46 | <rbuckton> | In C#, an interface is by default implemented implicitly:
But can be implemented explicitly:
Whether something is implemented implicitly or explicitly is purely up to the consumer of the interface |
| 05:47 | <Justin Ridgewell> | ^ Can we extend method names with . syntax to look up the lexical variable? |
| 05:47 | <rbuckton> | Wouldn't that just be []? |
| 05:48 | <Justin Ridgewell> | Without wrapping |
| 05:49 | <Mathieu Hofman> | can we advance the queue? |
| 05:49 | <rbuckton> | I'd rather just stick with []. without it you run into refactoring hazards |
| 05:49 | <Mathieu Hofman> | I'd like to reply |
| 05:49 | <Michael Ficarra> | it would've been great if all this excitement about protocols had been occurring on the issue tracker some time in the last 8 years |
| 05:49 | <Michael Ficarra> | better late than never, I guess |
| 05:49 | <hax (HE Shi-Jun)> | Extension proposal draft has syntax for that. |
| 05:49 | <snek> | i've always been excited about protocols |
| 05:49 | <Michael Ficarra> | not loudly enough! |
| 05:50 | <snek> | gus "snek" "protocols" caplan |
| 05:50 | <rbuckton> | I like protocols, though I'm not a fan of the post-hoc Proto.implement() approach. |
| 05:51 | <bakkot> | seems like this is an is/ought conflict |
| 05:51 | <rbuckton> | the upside of syntactic protocols is that there's the outside chance they can be statically optimized and you can have a self-contained class w/o depending on expression-level mutation |
| 05:51 | <bakkot> | ljharb is saying fields aren't the public shape |
| 05:51 | <Michael Ficarra> | protocols "gus" protocols "snek" protocols "caplan" |
| 05:51 | <bakkot> | lea is saying they should be |
| 05:51 | <Christian Ulbrich> | I find it a very special view on things, saying, that you could remove properties in a constructor, you could remove static fields too. Certainly in TypeScript nobody would expect this, because Classes or Interfaces are made up of public methods / fields. |
| 05:52 | <ljharb> | i'm 100% fine with a way to explicitly define the shape of an instance. but "the fields" are not the shape |
| 05:52 | <bakkot> | but like... why not |
| 05:52 | <bakkot> | it is true you can do dynamic stuff which makes the realized shape different from the list of fields |
| 05:52 | <ljharb> | because it's increasing the size of my API |
| 05:52 | <snek> | Michael Ficarra: do you see yourself having time to champion protocols these days? i may be down to co champion at least but i don't think i could individually spearhead it. |
| 05:52 | <bakkot> | ok, sure, that's a totally reasonable argument which is different from what was said just now, unless I missed it |
| 05:53 | <ljharb> | i did mention it briefly |
| 05:53 | <Michael Ficarra> | @rbuckton ^ there's declarative forms and dynamic/imperative forms for everything |
| 05:53 | <bakkot> | that is an "ought" argument rather than an "is" argument |
| 05:53 | <hax (HE Shi-Jun)> | I think it's actually already be public, for example d.ts must include that info. |
| 05:53 | <ljharb> | renaming a variable in my function shouldn't be a breaking change, nor should me moving between a public field and a constructor line |
| 05:53 | <bakkot> | in this context "public" means "to other code", not to build-time tooling |
| 05:54 | <ljharb> | right. through decorators is fine because that's something the class author has to explicitly opt in to |
| 05:54 | <bakkot> | again, totally reasonable position but I think lea has a fairly convincing case that (if we want this at all) making public fields part of the contract is the obvious way to do it |
| 05:54 | <ljharb> | and right now you can already make a class decorator that decorates your class with shape info if you like |
| 05:55 | <ljharb> | not implicitly imo. explicitly? maybe |
| 05:55 | <Mathieu Hofman> | I did not formulate my public field comment clearly apologies. I think I my next topic will clarify |
| 05:55 | <hax (HE Shi-Jun)> | To me (and many people) they are one thing, or at least should be consistent. |
| 05:56 | <bakkot> | how do you feel about the argument that moving something between the class prototype vs being added to each instance in the constructor should not be a breaking change? because that feels like exactly the same kind of thing, to me |
| 05:56 | <ljharb> | property placement is part of the API of an object |
| 05:56 | <ljharb> | the way the property got there is not |
| 05:57 | <bakkot> | why? I don't think users should think of property placement as being part of the API of objects, as a rule |
| 05:57 | <rbuckton> | IMO, public fields are part of the public API. IMO, doing this.x = in a constructor w/o some sort of public field declaration is bad practice |
| 05:57 | <bakkot> | if the documented way to use my objects is foo.bar(), it's on them if they were doing Foo.prototype.bar.call(foo) and that starts breaking |
| 05:57 | <Christian Ulbrich> | rbuckton: It certainly is in TypeScript. :) |
| 05:58 | <snek> | ron that opinion certainly applies to ts but has no observable (aside from override mistake) difference in js |
| 05:59 | <rkirsling> | yeah as somebody who's never used TS, that's a pretty foreign opinion to me 😅 |
| 05:59 | <bakkot> | concretely: I don't think "is this property looked up on the instance vs the prototype" is any more obviously part of the API than "is this property declared in the class or dynamically added in the constructor" |
| 05:59 | <rbuckton> | Today engines have to manage shape transitions in a constructor/function when you do this.x = . A fair amount of the discussion around field decorators came from implementers who wanted classes to have a fixed shape. |
| 05:59 | <Christian Ulbrich> | What an API is made of, is described in its documentation. There is no direct relation between a public field and a public API, it could also be an implementation detail, but let's understand what we are talking about with public API - public API means, that it is "available". |
| 05:59 | <snek> | shape is not an observable property in js |
| 06:00 | <rbuckton> | Fixed shape also very strongly applies to structs. You won't be able to do this.x = in a struct w/o a field declaration. |
| 06:00 | <ljharb> | that's a fair stance to hold. but nobody documents public field usage on their class - at best they document the final shape (which might be the same) in a TS type |
| 06:00 | <ljharb> | that's not entirely true (although semver means that). it's also arguable that anything reachable/observable is the API. |
| 06:00 | <bakkot> | there is almost universal agreement that function.toString is not considered part of the public API. so "available" is certainly not what I mean by "public API" |
| 06:01 | <ljharb> | yeah [[SourceText]] is an exception, it doesn't count for anything |
| 06:01 | <rbuckton> | It is certainly observable when you hit a performance cliff due to IC cache misses |
| 06:01 | <rbuckton> | It's not directly observable in JS as a language, but it is a fact of life in most engines |
| 06:02 | <snek> | that has nothing to do with whether its a public api though |
| 06:02 | <snek> | you can make your class slow with internal code as well |
| 06:02 | <snek> | if our only working definition of public api is hyrum's law how are we supposed to ever model anything |
| 06:03 | <Ashley Claymore> | ES5 style constructors have decades of optimizations |
| 06:03 | <rbuckton> | Fixed shape is still an important performance characteristic, so much so that it's baked into the struct proposal |
| 06:03 | <Christian Ulbrich> | Maybe the discussion is a little bit too much into what is a "public API" and what not, the question is, whether the Introspection proposal has its usages or not. I think this is the question to answer:
|
| 06:03 | <ljharb> | and i would say no, not at all |
| 06:03 | <rbuckton> | Which are also often the cause of major performance issues. |
| 06:04 | <Christian Ulbrich> | Personally I do not find an answer to this question easy. |
| 06:04 | <ljharb> | it definitely might be worthwhile to have class authors explicitly document their instance shape tho |
| 06:04 | <rbuckton> | Arbitrary field ordering and partial field assignments are a whole class of performance issue. |
| 06:05 | <ljharb> | also, re the queue, to restate: function toString doesn't count for anything |
| 06:05 | <ljharb> | angular 1 learned that the hard way |
| 06:05 | <rbuckton> |
this is terrible for performance and happens everywhere |
| 06:06 | <Christian Ulbrich> | Yes, you can have toString() lie :). |
| 06:06 | <ljharb> | not Function.prototype.toString.call tho (unless you replace that method ofc) |
| 06:06 | <snek> | who is parsing function toString |
| 06:06 | <ljharb> | angular 1 did |
| 06:06 | <rbuckton> | The above produces a class that can have three completely different shapes at runtime, which causes a host of issues with inline caching |
| 06:06 | <ljharb> | nobody else tho, hopefully |
| 06:07 | <Christian Ulbrich> | @snek I have to for AOP with JavaScript :) |
| 06:08 | <snek> | what is AOP |
| 06:08 | <Christian Ulbrich> | snek: Aspect-oriented programming. |
| 06:08 | <ljharb> | i had to google it too |
| 06:08 | <bakkot> | ... I kind of think we should a Class built-in, from which all class objects inherit (the classes themselves, not the instances) |
| 06:08 | <hax (HE Shi-Jun)> | Isn't that the signal that we miss the reflection ? I think public fields have the similar issue~ |
| 06:08 | <rbuckton> | Kind of what decorators are for. And the Angular 1 toString debacle is why Angular 2 heavily relied on decorator syntax |
| 06:08 | <bakkot> | and then we could have Class.prototype.getFields or whatever |
| 06:08 | <Christian Ulbrich> | rbuckton: But not in functions. |
| 06:09 | <ljharb> | not yet at least |
| 06:09 | <rbuckton> | not yet, though I already have two stage 1 proposal for this (function decorators and parameter decorators) |
| 06:09 | <Christian Ulbrich> | real ™ AOP is also about preconditions etc. at runtime, what else? 😀 |
| 06:10 | <Christian Ulbrich> | real real AOP also works on any kind of function anywhere in your source / function. |
| 06:13 | <Christian Ulbrich> | real real real AOP would create those dynamically. An AI could do that! Dynamic tracing of production code due to potentially identified threats without explicit instrumentation, why not? Of course the proper reaction would be, self-modifying code to alleviate problems! |
| 06:17 | <rbuckton> | 👮 |
| 06:21 | <rbuckton> | Do protocols support inheritance? like
|
| 06:21 | <ljharb> | i assume they'd support implements at least |
| 06:22 | <ljharb> | but yeah extends probably makes sense too, so you can still have required user fields |
| 06:22 | <bakkot> | yes https://github.com/tc39/proposal-first-class-protocols/blob/603c9ec53f134007d975654bbbec2a363aeae1e5/examples/monad-hierarchy.js#L11 |
| 06:22 | <rbuckton> | If they do, then they may have the same problem as mixins due to the diamond dependency problem. |
| 06:23 | <bakkot> | ... how so? |
| 06:24 | <rbuckton> | I may have misspoke? I need to consider it more. |
| 06:29 | <Michael Ficarra> | @rbuckton the example there is literally a diamond inheritance and it's not a problem for protocols because the names are always qualified by the protocol that defines them |
| 06:30 | <rbuckton> | Can you override a default method implementation from a protocol? |
| 06:30 | <rkirsling> | seems like it might be nice to temp check "who would block if it were / were not visible in the else" |
| 06:30 | <Michael Ficarra> | @rbuckton yes, and again, it's still qualified so still fine |
| 06:31 | <rbuckton> | And what happens if you do this:
|
| 06:31 | <Michael Ficarra> | works |
| 06:31 | <rbuckton> | What does "works" mean? Which implementation is on C2? |
| 06:31 | <jkup> | snek: I guess it doesn't matter but I'm surprised by the var comment. I thought your issue was that if the check fails the binding shouldn't exist? |
| 06:32 | <snek> | yeah i just don't care what var does. no code i have touched in the last 10 years uses var. |
| 06:32 | <jkup> | ok thank you |
| 06:32 | <snek> | so i mentioned that since since i have a hard stance and it presents one (of many) paths to advancement |
| 06:32 | <Michael Ficarra> | let's take this to DMs |
| 06:35 | <ljharb> | Justin Ridgewell: my bad, you're right about eslint |
| 06:35 | <Christian Ulbrich> | bottom-left will not be picked up by a linter today. I'll bet a Sapporo on that. However, I think making a rule for that, should not be difficult. |
| 06:35 | <danielrosenwasser> | I actually don't know if it's that much of a pain?
|
| 06:35 | <rbuckton> | The ... leaves a gap between acquisition and registration |
| 06:36 | <ljharb> |
will definitely error on https://eslint.org/docs/latest/rules/no-shadow, which all the popular configs have enabled |
| 06:36 | <snek> | we gotta be making features that enforce correctness by default rather than saying the person writing the code has to enforce the correctness. there is a mountain of quantitative evidence that patterns like this cause bugs and security issues. |
| 06:37 | <Christian Ulbrich> | ljharb: Yes, but only because you re-declared it. |
| 06:37 | <ljharb> | the bottom left is redeclaring it |
| 06:37 | <ljharb> | there's two let data ='s |
| 06:37 | <Christian Ulbrich> | yes but in the condition. I doubt there will be support for that, already. |
| 06:38 | <ljharb> | oh. well sure, in that case every linter would syntax error on it |
| 06:38 | <rkirsling> | how you gonna negate a declaration |
| 06:38 | <ljharb> | so either way i'll take my beer later :-p |
| 06:40 | <Christian Ulbrich> | this is to be decided. I'd go for no syntax error and use an updated eslint rule :) |
| 06:40 | <danielrosenwasser> | I actually am okay with Stephen's solution here - restrict else when if (using ) |
| 06:40 | <ljharb> | lol well yeah, obviously if the feature landed the rule would update to complain about the bottom left |
| 06:40 | <rkirsling> | excellent, Jake's question is exactly where we should focus |
| 06:41 | <Justin Ridgewell> | What was Jake’s question? |
| 06:41 | <rkirsling> | oh wait what |
| 06:41 | <rkirsling> | sadness |
| 06:41 | <bakkot> | ok so how am I supposed to write this in that case?
|
| 06:41 | <jkup> | did something get cleared? |
| 06:41 | <ljharb> | "is there still anyone who wants it visible in the else" was jake's question iirc |
| 06:41 | <rbuckton> | I'll be honest, I really disliked declarations in conditionals in Go, but I'll admit a lot of that ire comes from the lack of ternaries in Go. |
| 06:42 | <Devin Rousso> | maybe i shouldve done a temperature check lol |
| 06:42 | <Devin Rousso> | cause yeah getting an idea of how many are on each "side" would be great |
| 06:42 | <keith_miller> | Is the else problem also going to be essentially a blocker for pattern matching? |
| 06:42 | <Devin Rousso> | i do think the idea of disallowing else is really clever! |
| 06:43 | <keith_miller> | It seems like if we can't solve it here are we going to be able to solve it later? |
| 06:43 | <ljharb> | i don't think so |
| 06:43 | <Michael Ficarra> | how could you not know how many people are on each side at this point? |
| 06:43 | <rbuckton> | There's a bit of a difference though. Pattern matching doesn't currently treat if specially. It declares the bindings in the containing scope. |
| 06:44 | <bakkot> | you can't use pattern matching with using so my opinions are less strong |
| 06:44 | <rkirsling> | I thought temp check was super important there; I would be willing to let the meeting go an extra 2 minutes to get one in |
| 06:44 | <Devin Rousso> | i have a rough idea of who's who, but it would be nice to have confirmation |
| 06:44 | <Devin Rousso> | and frankly it was quite rapid at a few points |
| 06:44 | <ljharb> | we could make that usable but obv we'd have to make the usage of it work as you expect |
| 06:45 | <rbuckton> | Example of
|
| 06:47 | <Michael Ficarra> | it's overwhelmingly disallow in the else because, well, duh |
| 06:47 | <Justin Ridgewell> | I have no idea what that program means |
| 06:47 | <Steve Hicks> | But that's really a pattern matching thing. |
| 06:47 | <Devin Rousso> | yeah that's what i feel as well, but it also seems like there are a few who very strongly want it in the else |
| 06:47 | <rkirsling> | yes but data is better than vibes |
| 06:47 | <Michael Ficarra> | then do the temp check to confirm |
| 06:48 | <rbuckton> | I still maintain that, aside from using, decls in conditionals is otherwise fully covered by pattern matching. |
| 06:49 | <mgaudet> | (Side note: I didn't get temp-checked despite having TCQ open.... Despite my implementation concerns, I was leaning towards interning) |
| 06:50 | <ljharb> | it's perfectly fine to have two ways to do a thing tho. using pattern matching to get decls in conditionals is gross, and it'd be better to also have proper decls |
| 06:51 | <rbuckton> | To be clear, decls in conditionals in a language like Rust is pattern matching. |
| 06:51 | <ljharb> | it wouldn't be here because of the condition part |
| 06:51 | <snek> | i think we should have pattern matching in if statement heads |
| 06:52 | <rbuckton> | IMO, these are certainly not gross:
|
| 06:52 | <Steve Hicks> | I'd love to see pattern matching land - is there a reasonable path forward for it? |
| 06:52 | <snek> | its also an even better argument for else not binding, because there is no possible value to bind the variable to in the failure case |
| 06:52 | <ljharb> | i agree! but neither of those is just a declaration |
| 06:53 | <rbuckton> | I believe so, we just haven't had the opportunity to work on the proposal in a while. |
| 06:53 | <Michael Ficarra> | can you get on the queue? sometimes if you haven't interacted in a long time, you have to re-auth for things to start working again |
| 06:53 | <rbuckton> | Neither is if (let x = ...; ...) {} |
| 06:53 | <mgaudet> | Seems to be working. |
| 06:54 | <ljharb> | true. but that one isn't pattern matching :-) |
| 06:55 | <nicolo-ribaudo> | I guess strings are technically garbage collectable |
| 06:55 | <snek> | if (let truthy(x) = ...) {} |
| 06:55 | <rbuckton> | Consider the extractor case. if (opt is Option.some(let x)) actually checks the extractor matches, but what would if (let Option.some(x) = opt) { ... } do? |
| 06:56 | <Rob Palmer> | ^^ vote 1 |
| 06:56 | <snek> | i mean i would've expected the syntax to be if (let Option.some(x) = opt) |
| 06:56 | <snek> | but in all 3 of these its just syntactic choices |
| 06:56 | <bakkot> |
if we're going to let you write
then I want to write the above as
not your pattern matching thing |
| 06:57 | <waldemar> | The temp checks were useful |
| 06:57 | <rbuckton> | The first is pattern matching, which follows left to right evaluation. The second is assignment, which follows right to left evaluation. |
| 06:57 | <Aki> | Don't forget to write your summaries and conclusions!!! |
| 06:57 | <rkirsling> | this would be a useful three minutes for a temp check 😭 |
| 06:58 | <rbuckton> | Ah, extra let in the second example, fixed. |
| 06:58 | <snek> | my point was that i don't intuit any behavioral difference between these |
| 06:58 | <snek> | to me they are 3 ways to write the same thing |
| 06:58 | <bakkot> | rust literally has exactly this |
| 06:59 | <bakkot> | the if (let Some(x) = opt) { syntax |
| 06:59 | <danielrosenwasser> | I have a thought, but I think you will hate it. |
| 06:59 | <bakkot> | this committee is an exercise in hearing hateful things; hit me |
| 07:00 | <rbuckton> | let Some(x) = opt is exhaustive. If it doesn't match its an error. Just as let [x] = opt throws if opt isn't iterable. |
| 07:00 | <bakkot> | my point is that if you put it in an if then you would get the else, not an error |
| 07:00 | <bakkot> | this is very obviously how it should work, and is how it works in other languages with analogous features |
| 07:00 | <rbuckton> | There are a lot of issues with trying to extend destructuring syntax to pattern matching. |
| 07:01 | <snek> | i think we are conflating two different things here |
| 07:01 | <rbuckton> | Those languages can use pattern matching in declarations. JS can't because of decisions we made for how assignment and binding patterns work that preclude other pattern matching uses. |
| 07:02 | <bakkot> | but we can make extractors work like this |
| 07:02 | <bakkot> | can, and should |
| 07:02 | <bakkot> | I don't want extractors if we don't have this |
| 07:02 | <danielrosenwasser> | Basically a restriction where you can always write an else, but it's a ReferenceError to refer to a if (using) variable in an else block |
| 07:02 | <rbuckton> | I'm actually trying to very clearly delineate the two. Declarations can't be actual pattern matching. |
| 07:02 | <Steve Hicks> | Agreed. Is it the case that different options make sense depending on if your if is doing pattern matching? I.e. Rust is pattern matching and doesn't expose the binding in the else, Golang does not pattern match and does. |
| 07:02 | <bakkot> | seems fine as long as it's also a ReferenceError for the other kinds of declarations! |
| 07:03 | <rbuckton> | I investigated this several years ago: https://gist.github.com/rbuckton/df6ade207eecad4fc94cedc3aae79ceb |
| 07:03 | <danielrosenwasser> | I mean I'm fine with that too, it at least tells people "this can't be expressed this way, or you're probably making a mistake" |
| 07:04 | <rbuckton> | Specifically: https://gist.github.com/rbuckton/df6ade207eecad4fc94cedc3aae79ceb#extending-if |
| 07:04 | <rbuckton> | The pattern matching champions group were overwhelmingly opposed to extending existing syntax |
| 07:08 | <bakkot> | but seriously I would at least prefer that to the state where you can't write I do think it would be a very strange inconsistency, though, and would much prefer it to be an error for the other kinds of declaration as well. |
| 07:08 | <rbuckton> | IMO, if if (let Option.some(x) = opt) actually checks the extractor matches, then if (let [x, y] = z) also need to check and not throw, and that means to any level of depth within the binding pattern. |
| 07:08 | <bakkot> | I don't see much reason to want any declarations to be visible in the else when you can so easily just move them up a line. using is the only reason you need to be extremely careful with when bindings are and are not in scope. |
| 07:09 | <rbuckton> | move them up a line and surround the whole statement in {} |
| 07:09 | <bakkot> | if you want to be that careful with scope, sure |
| 07:09 | <bakkot> | but if you're not using using you don't actually need to be that careful |
| 07:09 | <rbuckton> | Isn't that the point of the proposal? |
| 07:10 | <bakkot> | IMO the point of the proposal is basically using, and the other declarations are just nice-to-haves which would not be adequate motivation for the proposal on its own |
| 07:12 | <Steve Hicks> | The proposal was originally written before using existed, so that's definitely an opinion. |
| 07:12 | <rbuckton> | I can maybe get on board with a narrowly focused if (using x = ...; ...) {} proposal without supporting var/let/const as it also short circuits the whole destructuring and extractor concerns as well, since neither are allowed in using. |
| 07:12 | <bakkot> | yeah I said the same thing when it was originally presented |
| 07:12 | <bakkot> | I think it would be very weird to leave out let and const at that point |
| 07:13 | <bakkot> | like, as a user, that would make no sense |
| 07:13 | <Steve Hicks> | Would that be open to abuse by just writing using for ordinary non-disposable objects? |
| 07:13 | <rbuckton> | No, because that's an error. |
| 07:13 | <rbuckton> | using x = 1 throws |
| 07:14 | <rbuckton> | it only allows null, undefined, and an object with [Symbol.dispose]() |
| 07:14 | <Steve Hicks> | At that point it's basically just try-with-resources |
| 07:14 | <rbuckton> | No, try-with-resources doesn't support conditions |
| 07:14 | <bakkot> | nnnnot really? it's still a conditional |
| 07:14 | <rbuckton> | And using started as a try-with-resources variant |
| 07:15 | <Steve Hicks> | (false -> throw and catch, maybe? but point taken) |
| 07:18 | <rbuckton> | I think we need to knuckle down and get the pattern matching proposal up to date and present it soon. We've lost some momentum over the last year and at least one of the champions has had to step back. |