10:06
<littledan>
I guess it's possible to implement such a rule whether Object.strictEquals is built-in or defined in user code. I'm still not really convinced that you want those semantics all the time (and continued assertions of "it's broken" aren't so persuasive to me), but if JS programmer does what to write those checks for their code, sure, they can go for it.
10:08
<littledan>
I feel like we might've added edge cases or functions in the past when there were specific requests made, but that that's not really the best design method in general. For one example, I'm not sure if `BigInt.asIntN` is all that useful, even if it had a role in selecting BigInt over Int64--we could've just chosen BigInt without adding that function.
16:47
<leobalter>
Bakkot: I'm really happy you're bringing do expressions back to the game. on slide 10: I believe it's ok w/ loops and it does not create anything we don't know. `for (let a of 'abc') a;` completes to 'c' already, this should not be "bad". It's just a pre-existing fact
16:48
<Bakkot>
leobalter: it's a fact very few people are exposed to currently, and which many people have expressed surprise at in the context of this proposal
16:48
<leobalter>
on slide 11: declarations is as bad as declarations in blocks.
16:48
<Bakkot>
?
16:48
<Bakkot>
declarations in blocks are fine in general
16:48
<Bakkot>
do you mean, in do-expressions?
16:49
<Bakkot>
the idea is that the prohibition on loops and declarations ending a do-expression would be applied recursively in the last statement(s) of the block, so that all of `do { let x; }`, `do { { let x; } }`, `do { if (foo) { let x; } else { 0; } }` etc would be a syntax error
16:50
<leobalter>
https://www.irccloud.com/pastebin/cKAO7oSY/
16:51
<Bakkot>
ah, that's specifically because of B.3.3 hoisting, which I am also proposing to prohibit in do-expressions
16:51
<Bakkot>
that code would give you an error in a module, which I think is reasonable
16:51
<Bakkot>
(or any other strict context)
16:51
<leobalter>
I believe this is a concern for userland, a linter should worry about it
16:52
<Bakkot>
hmm
16:52
<Bakkot>
I don't think there is any reason someone would want to end a do-expression with a declaration currently.
16:52
<leobalter>
I'm not objecting to anything but expressing a preference, to be clear here
16:52
<Bakkot>
so I don't see a benefit to allowing it
16:53
<leobalter>
I agree no one want to end a do-expression with a declaration, but I'd keep the semantics equivalent for blocks. We are just capturing the completion result
16:53
<leobalter>
it's not allowing it, it's actually not creating special rules to disallow it
16:54
<devsnek>
strong agree with leobalter but i think you knew that already
16:54
<leobalter>
most of these problems will be taken care of in strict mode / module code
16:54
<Bakkot>
my general philosophy is that if there is a place where a syntactic construct would always be surprising, we should just disallow that syntax
16:55
<Bakkot>
always be surprising or undesirable, I should say
16:55
<devsnek>
also `do {}` should just be undefined
16:55
<Bakkot>
`do {}` being undefined I am on board with
16:55
<Bakkot>
I'll start writing that instead of `void 0`
16:55
<devsnek>
lol
16:55
<leobalter>
I am really happy to see do expressions in the agenda, I'm a big supporter of this feature
16:56
<devsnek>
as for disallowing certain syntax
16:56
<devsnek>
i think its just kind of awkward at the statement level cuz you have to start worrying about what happens if you comment out a line
16:56
<Bakkot>
hmm, that's a fair point
16:57
<leobalter>
this is also a big thing: `do { throw 'foo' }` we solve the lack of throw expressions
16:57
<devsnek>
but not the tendency of people to throw strings :P
16:58
<leobalter>
don't ask me to form a full example in irc chat
16:58
<devsnek>
haha
16:58
<devsnek>
i think the main reason for throw expressions was concise bodies
16:58
<Bakkot>
for declarations, the other option is to change the completion value for the declaration to be the RHS (or undefined)
16:58
<devsnek>
at which point you might as well just drop the `do` and use a non-concise body
16:58
<Bakkot>
or in the case of class or function declarations the original value of the binding (because they are hoisted), though that's... awkward
16:59
<Bakkot>
devsnek: throw expressions also make sense in default parameters and a few other cases
16:59
<devsnek>
i think undefined makes the most sense
16:59
<devsnek>
oh fair point
16:59
<Bakkot>
I think if someone writes `do { function f(){} }` they should either get an error or `f`
17:00
<devsnek>
yeah i'm fine with making function declarations return the relevant function
17:00
<devsnek>
wait are function declarations mutable
17:00
<Bakkot>
yeah
17:00
<Bakkot>
and hoisted
17:00
<devsnek>
aw man
17:00
<Bakkot>
so that one is awkward; probably you want to do the original value of the binding, I guess?
17:00
<Bakkot>
which is weird
17:00
<devsnek>
yeah
17:00
<devsnek>
well i don't think binding fits into it
17:00
<Bakkot>
this is part of why I want to disallow declarations here :P
17:01
<devsnek>
its more like function declarations know the function instance they create
17:01
<devsnek>
without going through the binding
17:01
<devsnek>
i think we need to just very carefully go through completions
17:01
<Bakkot>
yeah, same thing
17:02
<Bakkot>
the surprising completions are mostly just declarations and loops
17:02
<Bakkot>
it is maybe a bit surprising that the completion of a `try { } finally { }` comes from the `try` and not the `finally`, but not that surprising I think.
17:03
<devsnek>
once you know what the deal with finally is
17:03
<leobalter>
should do expressions blocks always run in strict mode?
17:03
<devsnek>
well there is precedence with classes
17:04
<Bakkot>
leobalter: it's a little tempting, but the last time we discussed it people did not like having strictness change within a function body
17:04
<Bakkot>
as opposed to the boundary of a function
17:04
<devsnek>
or class
17:05
<devsnek>
given static initializers
17:05
<Bakkot>
classes are functions basically
17:05
<devsnek>
yeah i meant, since they appear to be within something shaped like a function `name parens block body`
17:05
<devsnek>
since they don't* appear
17:12
<Bakkot>
I am still leaning towards banning declarations as the last statement in a do, I think
17:12
<Bakkot>
they are just too surprising
17:13
<Bakkot>
unless we can change their completion semantics to be less surprising
17:14
<bradleymeck>
I think with destructuring any possible thing is surprising
17:16
<Bakkot>
would just having it be the RHS really be surprising, even with destructuring?
17:16
<Bakkot>
that's how assignments work (... I hope)
17:36
<devsnek>
Bakkot: it can have more than one rhs
17:36
<devsnek>
`let a = 1, b = 2`
17:45
<Bakkot>
eh, `a = 1, b = 2` completes to `2`; seems fine to me to do the same thing when there's a `let` in front of it
17:46
<Bakkot>
and to give `undefined` when there's no initializer, though that one seems not useful (but at least not surprising)
17:46
<Bakkot>
no initializer on the last declarator, that is
17:53
<bradleymeck>
Bakkot: the debugger statement is also kind odd
17:54
<devsnek>
it just returns whatever the host wants
17:54
<bradleymeck>
does anywhere not return undefined?
17:54
<devsnek>
i don't think so
18:05
<ljharb>
Bakkot: you could use `do { throw x }` in default params etc too tho, no?
18:06
<ljharb>
Bakkot: does the completion of a try/finally come from the finally if the finally has a `return`?
18:28
<Bakkot>
ljharb re first question: yes, that's the point
18:29
<Bakkot>
re second question: yes, or a `break`, which is actually relevant because `do { x: try {} finally {0; break x} }` would be legal under the proposal as I intend to propose it
18:29
<Bakkot>
though, you know, don't write that code
18:33
<ljharb>
hard agree
19:34
<rkirsling>
oh geez I can't believe I hadn't thought about putting function decls in a do block
19:36
<rkirsling>
Bakkot: I think `do {}` has to be undefined though, right? how else can if-without-else work? (and only allowing if-with-else would be uncomfortable...)
19:36
<Bakkot>
if-without-else has a completion value; it's `undefined`
19:36
<Bakkot>
`0; if (false) ;` completes to `undefined`, not `0`
19:37
<Bakkot>
but yeah I think undefined makes sense
19:37
<ljharb>
and `0; if (true) ;` ?
19:37
<Bakkot>
also undefined
19:37
<ljharb>
ah k, but `0; if (true) 1;` would be 1?
19:37
<Bakkot>
indeed
19:37
<ljharb>
sgtm
19:38
<rkirsling>
I hadn't thought about that, but yeah, I think requiring that knowledge incurs the trivia cost jorendorff talked about
19:39
<rkirsling>
probably best for the user to be correct for the wrong reason 😅
19:40
<rkirsling>
hmm pipeline still needs to be added to the agenda
19:40
<rkirsling>
hurry up TabAtkins, before it spills into the following meeting XD
19:41
<TabAtkins>
No it's going in the next
19:41
<TabAtkins>
Instead
19:41
<rkirsling>
ohh I misunderstood
19:41
<rkirsling>
sounded like you had your arguments all in order 😅
20:06
<rkirsling>
I don't actually understand what's being proposed with the spaceship operator thing
20:07
<rkirsling>
is it dependent upon operator overloading?
20:08
<ljharb>
rkirsling: it's going for stage 1, so it's just about solving a problem :-)
20:09
<ljharb>
rkirsling: but that solution would be `a <=> b` as sugar for `a[Symbol.compare](b)` or similar, which would return 0, a negative number, or a positive number
20:09
<rkirsling>
I see
20:09
<ljharb>
rkirsling: the same semantics it has in ruby already
20:12
<rkirsling>
but is that just following the suit of a general operator overloading mechanism in Ruby?
20:13
<rkirsling>
not that intimately familiar with Ruby but I'm imagining something like `__add__ ` in Python
20:19
<rkirsling>
yeah looks like it's the same thing except that Ruby allows `<=>` as a function name
20:19
<rkirsling>
(how very Scala-like)
20:50
<ljharb>
well sure, it does just fall out of ruby's overall semantics
20:51
<ljharb>
but the specific use case is valuable; ie, a generic protocol to compare values
20:51
<ljharb>
strings have localeCompare, numbers have subtraction, other types don't have anything
20:52
<rkirsling>
yeah no I'm not worried about it being a valid problem to solve
20:53
<rkirsling>
I was just confused by what's being proposed, since it'd be weird to have a proposal depend on operator overloading and not be clear about that
20:55
<ljharb>
it very much does not
20:56
<ljharb>
instanceof already calls into a symbol protocol, as does ==
20:56
<ljharb>
this is just another one of those
20:57
<jridgewell>
`==`?
20:58
<ljharb>
doesn't it? with Symbol.toPrimitive?
20:58
<ljharb>
or maybe only if one of the types is a primitive, i forget
20:58
<rkirsling>
I gotcha
20:59
<devsnek>
Symbol.parenthesized when
20:59
<ljharb>
either way there's precedent with instanceof
20:59
<devsnek>
wasn't that more about finding some way to describe instanceof behaviour
20:59
<devsnek>
on function instances or something
21:00
<ljharb>
i don't know the motivation, i know it made an unreliable operator useless :-p
21:00
<ljharb>
but that's because instanceof is something that often needs to be known robustly; comparison isn't
22:12
<rkirsling>
I actually didn't realize Symbol.hasInstance existed until days ago
22:12
<rkirsling>
what was the motivation there?
22:20
<Bakkot>
masochism, presumably
22:22
<drousso>
omg same
22:22
<drousso>
and it's existed for a while too
22:22
<drousso>
o.0