05:08
<devsnek>
surprisingly useful https://gc.gy/56273905.png
05:09
<ljharb>
devsnek: tbh that `.spec` thing seems like it'd be a pretty handy standalone npm package
05:10
<devsnek>
well its not magic
05:10
<devsnek>
it uses the `// #sec-xyz` comment above every function in engine262's source
05:10
<ljharb>
ah ok
05:10
<devsnek>
i agree though
05:10
<devsnek>
i wanted to add something similar in node's repl
05:10
<devsnek>
for js stuff and node stuff
05:10
<devsnek>
though it would've been mdn not the spec in that case
05:14
<ljharb>
i'd want it for the spec :-p
05:30
<Bakkot>
new proposal? :D
05:30
<Bakkot>
the ultimate reflection mechanism
05:30
<Bakkot>
actually I guess to qualify as "ultimate" it would also need to include an interpreter for spec-ese
05:31
<devsnek>
Array.prototype.flat.__doc
05:33
<Bakkot>
`Set.prototype.add = spec.evaluate(spec(Set.prototype.add).replace('If value is -0, set value to +0', 'If false'))`
05:37
<devsnek>
oh gosh
13:58
<Sirisian>
littledan, I was looking at the operator overloading proposal. Would it be fair to say a lot of the complexity in the proposed syntax is due to a lack of function overloading? I understand it's stage 1.
13:59
<littledan>
I don't understand how function overloading would relate to it. it's true that the proposal's contents are largely about the dispatch semantics.
14:00
<littledan>
I don't think you'd want function overloading to behave with the restrictions that operator overloading is defined to have
14:00
<Sirisian>
The static kind of design?
14:01
<Sirisian>
(I'm not fully clear on the implementation specifics, was just reading the issues).
14:18
<Sirisian>
Would it be insane to use a TS-like syntax https://github.com/sirisian/ecmascript-types#classes-and-operator-overloading I'm not really clear on the big picture of what slows things down in V8 and such in regards to operator overloading. Is it being able to define new operators on individual instances that would require lookups and be unworkable? So the operators must be on global class types and all or nothing for all instances?
14:20
<Sirisian>
(Also I realize that Symbol doesn't work. I added that a while ago when someone suggested it. Apparently that's a bad idea).
15:32
<jmdyck>
Bakkot: so `spec.evaluate(str)` would return a function object that, when called, performs the algorithm steps in `str`?
15:32
<Bakkot>
that would be the idea!
15:32
<Bakkot>
(to be clear this is not a serious proposal)
15:37
<jmdyck>
yeah, it didn't sound entirely serious. Still, I think it'd be possible.
15:51
<shu>
Bakkot: i'd feel more comfortable with a spec.evaluate if we first sat down and worked through the meta-machinery
15:52
<shu>
ecma261.5, the ecma262 metalanguage
15:53
<Bakkot>
working on it
15:54
<Bakkot>
michael ficarra and I have a preliminary linter integrated with ecmarkup
15:54
<Bakkot>
so we can start enforcing stuff like "variables are defined before use" and so no
15:54
<shu>
i'm interested in what the linter thinks about lets-in-branches
15:55
<Bakkot>
(that rule isn't implemented yet, to be clear, but should be pretty straightforward)
15:55
<shu>
i'm interested in the policy question
15:56
<Bakkot>
for now I'd want to start with allowing them, since they're in the current spec
15:56
<Bakkot>
and if we eliminate them we can update the linter to enforce that
15:56
<Bakkot>
I don't actually mind them much though
15:56
<shu>
yeah i like them tbh
15:56
<shu>
at least the fairly structured version where two branches both introduce the same alias
15:57
<Bakkot>
I think there might be a place or two where there's a "If Foo let X be *" without a corresponding else, and later usages of X also guarded on Foo
16:04
<shu>
that also seems fine to me
16:04
<shu>
and could be checked by the linter with sufficient sophistication
16:30
<devsnek>
littledan: I had an idea about operator overloaded where you try to make it as scoped as possible
16:30
<littledan>
devsnek: Yes?
16:31
<devsnek>
sort of like `let x = with operator xyz { a + b }`
16:31
<devsnek>
this lets it be fairly dynamic
16:32
<devsnek>
you can put as much in the block as you want but overloaded operations tend to happen in clumps so they should stay fairly small
16:33
<littledan>
devsnek: Would that be a do expression?
16:33
<devsnek>
it could be, yes
16:33
<littledan>
(I mean, what were you picturing? what else would it be?)
16:33
<devsnek>
I haven't formalized this idea that much
16:33
<devsnek>
if we have do expressions it would make sense to (ab)use them here
16:33
<littledan>
I mean, to me, curly brackets with code in them feel like they should have statements in them
16:34
<littledan>
if it's an expression, I'd imagine parentheses
16:34
<devsnek>
a + b is an expression statement
16:34
<littledan>
right
16:34
<devsnek>
so yeah it uses completion
16:34
<littledan>
so, it'd work as a do expression
16:34
<littledan>
if we're OK with using completion values, that'd be fine. I guess no one has driven this to Stage 2, but it seemed like dherman made good progress last time it was discussed
16:35
<devsnek>
but anyway since it encourages small scoping, you can make the protocol more dynamic
16:35
<littledan>
hmm, I don't think I follow that part
16:35
<littledan>
I think we need to be static just for the integrity goals anyway
16:35
<devsnek>
since you're only paying for dynamic behaviour inside the block
16:36
<littledan>
"paying for" makes sense when thinking about performance cost, but the integrity things are sort of considered serious either way. The intention isn't that you're opting into chaos mode, but rather into something contained
16:36
<devsnek>
integrity?
16:37
<littledan>
see "predictability" in https://github.com/tc39/proposal-operator-overloading/blob/master/README.md#design-goals
16:37
<devsnek>
hm I think I feel exactly the opposite
16:37
<littledan>
hmm how so?
16:37
<devsnek>
they should be dynamic and changeable imo
16:37
<littledan>
why?
16:38
<devsnek>
more javascripty I guess
16:38
<devsnek>
that's why I like this language
16:38
<littledan>
lots of people have told me specifically, operator overloading shouldn't happen in JS because then it'd be too dynamic and changeable
16:38
<littledan>
so, I was trying to respond to that and find something contained
16:38
<devsnek>
all I've heard is that dynamic shouldn't happen because of performance
16:39
<littledan>
so, I guess I've been a little sloppy about keeping quotes around, but I've personally heard more concerns than just that
16:39
<devsnek>
fair enough
16:39
<littledan>
let me see what I can dig up
16:39
<devsnek>
I really don't like the static stuff though
16:39
<littledan>
I mean, for example, ljharb at the last TC39 meeting was saying operator overloading would make JS more confusing, wasn't he?
16:40
<devsnek>
I think that's mostly about wide scoping of the overloads
16:40
<devsnek>
if you have these narrow scopes it's very obvious when it happens
16:40
<devsnek>
although you still have the issue of forgetting to scope
16:40
<littledan>
you could also look at the responses here: https://twitter.com/littledan/status/1024958066066898944
16:41
<littledan>
so, i was specifically trying to defend against certain "attacks" against integrity in this proposal. Probably I didn't do a good enough job explaining this in the repo, since people keep asking me the same questions about making more dynamic
16:41
<littledan>
so that's something for me to work on
16:42
<devsnek>
I think operator overloading works better when it's by intention instead of by operator
16:43
<devsnek>
like how in rust you implement deref, not the star operator
16:43
<devsnek>
I think people saying "operator overloading is bad" tend along that pathway
16:44
<littledan>
hmm, do you have ideas for what that would mean concretely, given the operators we have in JS?
16:46
<devsnek>
I don't know if I have a concrete answer
16:49
<devsnek>
it occurs to me that people use macros for this in rust, which is almost like my scoping idea
16:49
<devsnek>
let x = vec_ops! { a + b }
16:52
<littledan>
yeah, I think that's a good thing to look into, but at the same time, I feel like it's appropriate that the operator overloading proposal uses "+" to identify overloading things like a+b
16:52
<littledan>
and, I don't think this has to do with the responses to my tweet, which were half about operator overloading making all JS code opaque and confusing
16:52
<littledan>
so the concern was on the usage side, not the definition side
16:53
<devsnek>
yeah that's what I mentioned above, with small scopes making it clearer where this happens
16:53
<littledan>
Sirisian: If we can think of a more intuitive, TS-like syntax, then I'd be all for using it. I was thinking about using decorators somehow, but I was also thinking about avoiding the dependency
16:53
<devsnek>
of course if scopes are involved you run into the problem of forgetting to use one
16:54
<littledan>
rbuckton has some ideas about nicer syntax too, but I can't figure out how the details would fit together
16:55
<devsnek>
could also use some modified operator form
16:56
<devsnek>
a @X+ b to add a and b together using X's rules
16:56
<Sirisian>
littledan, Do you still work on V8? Was curious.
16:56
<littledan>
not really, but my coworkers in Igalia do
16:57
<devsnek>
i think you've still got some TODO comments in v8
16:57
<littledan>
devsnek: That wouldn't meet the goals of letting us generalize BigInt and Decimal
16:57
<littledan>
yeah, I think I left a lot there...
16:57
<littledan>
I codesearched myself the other day and yeah
16:57
<littledan>
sorry
16:57
<devsnek>
1n @BigInt+ 1n
16:57
<devsnek>
lol you're definitely not the only one who leaves todos
16:58
<littledan>
devsnek: By "explain", I mean make it as if BigInt were a feature added through operator overloading
16:58
<devsnek>
I'm not sure that's inherently possible
16:59
<devsnek>
if we require additional syntax at or around usage sites
17:16
<Sirisian>
I'd probably explicitly mention using operator overloading for polyfilling types like you mentioned. Personally I want to polyfill all the types in my proposal. const a = new uint32(5); a /= 2; :O Once thought only possible with BigInt. Truly a paradigm switch. Complex numbers, vectors, and matrices. Should probably just make an explicit list of use cases and examples.
17:20
<Sirisian>
Also maybe I missed something, but I didn't understand the a.contents stuff in the code sample.
18:03
<Sirisian>
Just looked at it again. I thought it was extending the other library vector when I skimmed it. I get it now.
18:38
<jmdyck>
Bakkot: yes there are cases like that ("If Foo let X be *" without a corresponding else, and later usages of X also guarded on Foo)
22:00
<littledan>
devsnek: The idea has been that you'd imagine there would be an "operator overloading prelude" for the built-in types. It's an action item I have (from Mark) to actually write this prelude, to prove it's possible.
22:01
<devsnek>
is that tangible to user code?
22:01
<littledan>
Sirisian: Yes, i've been trying to accumulate use cases, and I'd appreciate your help in that. Feel free to make a PR to the explainer to add more use cases
22:01
<littledan>
devsnek: No, in general, you can't reflect over code in JS... how would it be tangible?
22:02
<devsnek>
if its not tangible then explaining it doesn't matter
22:02
<littledan>
I don't know what you mean by being tangible
22:02
<littledan>
maybe I'm not explaining the sense of "explaining" very well...
22:02
<devsnek>
js code can observe that there is a prelude and that it contains BigInt and Number
22:03
<littledan>
well, you can observe it by doing arithmetic calculations on BigInt and observing that it works rather than throwing a TypeError
22:03
<littledan>
that's the exact same way that you'd observe it for your own types
22:03
<devsnek>
ok so then again
22:03
<devsnek>
there's no point to defining a prelude
22:03
<littledan>
the goal is that you can do your own BigInt-like thing, and it'd really work
22:03
<devsnek>
because we're talking about behaviour not declarations
22:03
<littledan>
not sure what you mean. "defining a prelude" is a design-level exercise
22:03
<littledan>
(like writing spec text or explainers)
22:04
<devsnek>
i'm not sure how that matches the goal of explaining how bigint works
22:05
<littledan>
let's talk about this another time. I don't really know how to get across this concept of "explaining". I'll think about it some more.
22:05
<littledan>
"explaining" is a kind of TC39 jargon that predates me in committee; maybe it's not the best word
22:05
<devsnek>
i thought it meant representing some behaviour in a way that js code can also interact with
22:05
<devsnek>
like toStringTag
22:06
<devsnek>
if js code can't interact with the prelude it doesn't matter whether the prelude exists or not, its just some imaginary thing
22:08
<littledan>
so, ES6 explained a bunch of things in a way that also added tons of dynamism and reflection. For reasons that I tried to explain, we don't really have the option of adding all that dynamism in this case. But the core of "explaining" isn't dynamism or reflection, but the idea that the thing that's built-in is also something that you could do in user code. That's something real too.
22:09
<littledan>
(you might consider things without dynamism/reflection bad, or that this feature isn't worth it, but that doesn't mean that it isn't "explaining")
22:09
<devsnek>
to me it is like saying we're adding toStringTag but then not getting rid of [[ClassName]]
22:09
<devsnek>
or [[Class]] or whatever it was called
22:10
<devsnek>
like the magic is still there, on a separate layer from the stuff js can do
22:10
<devsnek>
bigint magically works in any scope and there's no js equiv
22:10
<littledan>
Well, there's some things that would have to be pretty special forever, like how + works with strings and non-strings. But I think most of the arithmetic operations should be completely explainable in terms of this general mechanism
22:11
<littledan>
BigInt would work with this "prelude" theory. That's the one special case
22:11
<devsnek>
if the prelude is invisible to js it doesn't exist
22:11
<littledan>
it's a concept, sure. (does anything really exist?)
22:11
<devsnek>
no i mean
22:12
<devsnek>
bigint is still special
22:12
<devsnek>
in the same way
22:12
<littledan>
yes, but it's special in just one way; it's not *as* special. That's how I'm defining the design goal, the only way that I can see this matching up with the need to have the operator overloading declarations be scoped
22:12
<ljharb>
would the small scope version allow operator stuff to be less static?
22:13
<devsnek>
its like if you said "every time a function is invoked, a parallel universe is created where the function is evaluated"
22:13
<littledan>
ljharb: In my opinion, no. Do you think it would? why?
22:13
<ljharb>
personally the second-class nature of the current operator (and decorators) proposal is a big sticking point for me
22:13
<devsnek>
from the perspective of js you could never observe such a thing
22:13
<devsnek>
so it doesn't matter
22:13
<ljharb>
devsnek: with a dep graph where half of the operators are transpiled and half are native, it'd be observable, no?
22:13
<littledan>
you can't observe "use strict", but we stick it in modules implicitly... I'm not really sure what you're talking about, why this is a goal
22:14
<ljharb>
which
22:14
<devsnek>
what are you talking about
22:14
<devsnek>
you can add use strict to code
22:14
<devsnek>
that is an observable change to js code
22:14
<littledan>
yes, just like adding `with operators from` delcarations
22:14
<devsnek>
i don't mean reflection
22:14
<devsnek>
i mean what humans using js can observe and interact with
22:14
<devsnek>
from that perspective bigint is just as magical
22:15
<devsnek>
right now there could already be a prelude with your behaviour
22:15
<devsnek>
adding or removing it doesn't change anything
22:15
<littledan>
BigInt is built-in. The idea is that it's special in a well-scoped way, limited to just what you could do with a prelude, not that it's *arbitrarily* special
22:15
<littledan>
that's the design goal I'm working towards. You can disagree about whether it's a worthwhile goal, but that's what I'm trying to communicate.
22:16
<devsnek>
your goal doesn't make sense to me
22:16
<littledan>
OK
22:16
<devsnek>
i can't judge whether it is worthwhile or not because it appears to me to be a non sequitur
22:18
<devsnek>
ljharb: my idea with the scoped version i talked about above is that it would allow more dynamicness
22:18
<ljharb>
meaning like, a protocol?
22:18
<devsnek>
yeah
22:19
<devsnek>
no need for anything static
22:19
<devsnek>
but dan said the static-ness was partially because people wanted it to have integrity
22:20
<ljharb>
what kind of integrity
22:20
<ljharb>
like, how + should be commutative?
22:20
<ljharb>
or something else
22:20
<devsnek>
i assume it means you can't patch someone's overloads
22:20
<devsnek>
which seems rather unjavascripty to me
22:21
<ljharb>
unless you've frozen it, i agree
22:22
<ljharb>
that's an expectation i have for builtins, but not for user code
22:23
<devsnek>
they have configurable: false for toStringTag
22:24
<ljharb>
toStringTag is a special (bad) case that i don't see as related to operators
22:28
<Bakkot>
devsnek: you can't patch someone's overloads today
22:28
<Bakkot>
like you can't redefine what "+" means in my code
22:28
<devsnek>
there aren't overloads today
22:28
<Bakkot>
so why would... we want to... start letting people do that?
22:29
<Bakkot>
I don't think "let other people change the semantics of my code" is really a goal anyone on the committee has
22:29
<ljharb>
that's exactly what operator overloading is trying to do
22:29
<Bakkot>
no it is not
22:29
<ljharb>
let other people define the semantics of my code
22:29
<Bakkot>
no?
22:29
<Bakkot>
not without my explicitly opting in
22:29
<ljharb>
whether people can do it once, or more than once, doesn't seem that different to me
22:29
<ljharb>
that's the same as referencing any property on any object tho
22:30
<ljharb>
you opt in to using that property, and it's possible it could be changed later
22:30
<ljharb>
(when you don't destructure it, obv)
22:30
<Bakkot>
and assuming it's not frozen, which in this proposal it would be
22:30
<Bakkot>
so hey, all is well
22:31
<ljharb>
so you mean like, it's a symbol protocol, but the syntax for declaring it freezes it?
22:32
<ljharb>
if so, that does seem reasonable to me; anyone can participate but the default/ergonomic behavior makes it robust
22:44
<Bakkot>
I think it also destructures when entering the block, so it's defensive twice
22:44
<Bakkot>
don't remember exactly though
22:44
<Bakkot>
it was a very early stage design
22:45
<Bakkot>
ah, yeah, it reads the Operators property and that thing can only be made by a built-in Operator factory which produces immutable values, cool
22:46
<Bakkot>
anyway obviously someone can just define the overloaded functions themselves in a way which has their behavior change over time
22:46
<Bakkot>
point is, you have to opt in to using someone else's operators, and random third-party code can't just muck with it