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 |