00:24
<rkirsling>
(whining aside though, it'll probably be beneficial to have a more structured schedule for a bit, lol)
02:09
<leobalter>
devsnek: congrats! Don’t stress out to much, it will probably be better to focus on the onboarding and take some rest if necessary instead of much of TC39 stuff. Don’t let the FOMO take out your energy.
14:47
<Bakkot>
morning all
14:51
<rkirsling>
mornin'
14:55
<bterlson>
TCQ: https://tcq.app/meeting/KfmX
14:56
<chicoxyzzy>
meeting info link in the topic is outdated. should be https://github.com/tc39/Reflector/issues/279
14:58
<chicoxyzzy>
thank you Rob :)
14:59
<mathiasbynens>
did anyone create notes docs already? happy to update the short URLs again
15:01
<Bakkot>
mathiasbynens they're in the reflector, yeah
15:01
<Bakkot>
also reminder to all not to link the notes here, in this publicly logged channel
15:02
<mathiasbynens>
i don't see them in https://github.com/tc39/Reflector/issues/279
15:02
<mathiasbynens>
i see, #294
15:06
<michaelficarra>
good morning everyone :-)
15:08
<howdoi>
Good morning! :)
15:08
<littledan>
if you call on me next, I can give my standard IPR disclaimer
15:08
<littledan>
I imagine Istvan's thing is not what was being asked about
15:09
<littledan>
akirose: ^
15:09
<mpcsh>
akirose: your headphones 😂
15:09
<mpcsh>
so fetch
15:09
<rkirsling>
+1
15:10
<rkirsling>
littledan: you kind of look like you're interrogating us with that light :p
15:10
<littledan>
heh I don't have my awesome coworking space setup
15:10
<littledan>
my partner is planning on building a nice planter behind me and hanging up some of his art so it can show up in my video calls, but I guess we didn't plan for the light
15:11
<rkirsling>
that sounds nice though :)
15:13
<rkirsling>
did you just say mancy
15:13
<rickbutton>
mancy
15:36
<shu>
i'm confused about this slides sharing
15:36
<shu>
*i* can control the slide?
15:36
<Bakkot>
oh no
15:37
<rricard>
deep powerpoint integration probably
15:37
<Bakkot>
that is too much power
15:37
<shu>
wait when i'm jumping around
15:37
<shu>
am i making it jump around for other viewers, or just myself
15:37
<rricard>
it's not jumping for us
15:37
<shu>
ok
15:37
<shu>
whew
15:37
<rricard>
you can peek ahead
15:38
<rickbutton>
I assume that doesn't work for Google Slides
15:38
<rricard>
I would assume that yes
15:39
<rricard>
you can always export your slides in ppt
15:40
<Bakkot>
presumably one would need to actually have ppt lying around for that to do you any good
15:40
<Bakkot>
I don't think I have used a machine with ppt since high school
15:41
<Bakkot>
oh, teams is a ppt viewer apparently, neat
15:45
<akirose>
fwiw i literally just uploaded Istvan's ppt that he had emailed to the chair straight to the teams client
15:45
<akirose>
no ppt.app launched
15:46
<ljharb>
phew, irc is working again
15:46
<ljharb>
(for me)
15:48
<akirose>
draft schedule link added to reflector#279
15:54
<littledan>
these editorial improvements are awesome!
15:55
<marja_>
+1
15:56
<rkirsling>
+1
16:01
<michaelficarra>
thanks littledan :-)
16:23
<littledan>
akirose: *green heart emoji* been feeling similarly
16:23
<rickbutton>
100000%
16:26
<devsnek>
is tcq showing everything or just stuff for today
16:26
<robpalme>
everything
16:26
<robpalme>
we chew through as much of it as we can
16:27
<robpalme>
it may not yet be fully populated but that is the intent
16:27
<devsnek>
cool
16:27
<devsnek>
do we have that hackmd schedule this time around
16:28
<Bakkot>
this channel is public and should not have the notes doc linked in it
16:28
<ryzokuken>
devsnek: we do
16:28
<Bakkot>
robpalme ^
16:28
<rickbutton>
devsnek: the hackmd is on the reflector issue for the meeting, its at the top, "Draft Schedule"
16:29
<ljharb>
robpalme: Bakkot should we move today's notes to another URL?
16:29
<Bakkot>
ehhhh it's probably not worth worrying about
16:29
<ystartsev>
i can move it
16:29
<ystartsev>
either at lunch or eod
16:30
<devsnek>
thanks
16:30
<ystartsev>
any preference?
16:34
<littledan>
yeah, I agree that late agenda items should be deprioritized
16:35
<ryzokuken>
Isn't today a holiday in parts of Europe?
16:35
<leobalter>
ryzokuken: it is
16:36
<ryzokuken>
that's likely the issue, I guess 😅
16:44
<Bakkot>
jridgewell I am glad/impressed you know those NamedEvaluation details off the top of your head
16:45
<Bakkot>
I just reviewed this change and I still don't
16:45
<rkirsling>
note that ease for polyfill doesn't correspond to ease for impl
16:45
<ljharb>
shu: to clarify, chrome is shipping it with or without the inferred name?
16:45
<shu>
ljharb: without currently, because it's not in the spec
16:45
<ljharb>
thanks
16:45
<shu>
ljharb: if it is added, there is plenty of time to add it in before it hits stable
16:46
<ljharb>
gotcha
16:46
<ljharb>
drousso: you had thoughts on the issue thread btw
16:46
<drousso>
ya
16:46
<drousso>
i don't feel strongly
16:47
<drousso>
i am slightly towards "no" because of the short circuiting behavior
16:47
<Bakkot>
short circuiting behavior actually leans towards yes, I think
16:48
<Bakkot>
because with short circuiting it desugars to `a && a = function(){}`, which gets named
16:48
<rkirsling>
the tricky part is that while that is the desugaring, it's not the current code you would write
16:48
<ljharb>
or `if (a) { a = function () {} }` which also gets named
16:51
<drousso>
+1 to what rkirsling
16:51
<drousso>
said
16:51
<littledan>
personally, I don't see the size of the Babel output, or the desugaring, as a very strong argument one way or another
16:51
<littledan>
it's more about the general pattern that, in these sort of direct syntax assignment cases ending in = or :, you do name assignment
16:51
<littledan>
(sorry for caucusing before...)
16:52
<Bakkot>
yeah, agreed with littledan
16:53
<littledan>
sorry, the conclusion was yes, go ahead with named evaluation?
16:54
<ljharb>
sounds like yes, infer the name, as long as implementors can commit to implementing that
17:08
<Bakkot>
petition to consider shorter lunch breaks the next three days
17:09
<ljharb>
esp considering we're not all eating lunch at the same times when remote
17:09
<Bakkot>
I just had breakfast, so I'm not going to eat lunch, so I'm just sitting around
17:16
<devsnek>
is iterator helpers happening now
17:16
<jridgewell>
It's a tech check
17:16
<jridgewell>
We're on break till the new hour
17:17
<devsnek>
ah ok
17:18
<robpalme>
***Note-takers and Note-readers*** Today's notes have been migrated. Please find the new link here: https://github.com/tc39/Reflector/issues/279
17:29
<akirose>
i'm gonna mention this when we reconvene, but… we have way, way more time on the agenda than we have meeting time. use that information as you will.
17:33
<rkirsling>
folks in the breakout room feel like a one-hour lunch break doesn't really make sense under all-remote conditions
17:36
<bterlson>
rkirsling: as in, it's too long?
17:37
<rkirsling>
yeah
17:38
<rkirsling>
as in, like, even if you're in the appropriate time zone you might not need that long of a block of time when you're connected remotely anyway
17:38
<bterlson>
I dunno, I just finished cooking lunch, don't have that much time to eat :-P
17:40
<jridgewell>
The difference being it's ok to mute yourself and eat as presentations are going on
17:40
<jridgewell>
It's a little different than when we're in person
17:40
<shu>
shorter break time sgtm
17:41
<jridgewell>
Also the side discussions are much louder in-person, so having a long lunch break was nice
17:50
<ystartsev>
michaelficarra: are you around?
17:56
<sffc>
Is anyone here well-connected enough to get us an invitation to Clubhouse for the hallway track? https://www.wired.com/story/what-is-clubhouse-why-does-silicon-valley-care/
17:58
<akirose>
"a new social network more exclusive than Berghain" AHAHAHAHAHAHAHAH
17:58
<robpalme>
we are restarting in 1 minute!
18:02
<robpalme>
starting now!
18:04
<devsnek>
if there are questions about iterator helpers stuff i can address i'm watching the channel here but not actively listening to the call
18:07
<Bakkot>
ppt integration seems much worse than the share-screen integration
18:11
<ryzokuken>
akirose: `Intl.DurationFormat` is today according to https://hackmd.io/@tc39-chairs/rylG45f2L#1300-CDT, but it's not on the agenda.
18:11
<ystartsev>
yep..
18:12
<michaelficarra>
these slides are really good
18:13
<rbuckton>
Upstream iterator was never started either though
18:13
<littledan>
enclosing finally blocks around the current yield pause point are called by generator return FWIW
18:14
<ljharb>
eesh, i didn't realize the slides were advanced, i was stuck on slide 5. guess i'll open the link myself
18:14
<Bakkot>
iterators don't get started
18:14
<Bakkot>
generators get started
18:14
<Bakkot>
... I think
18:14
<devsnek>
iterator is just a protocol
18:14
<devsnek>
there's no behaviour
18:14
<Bakkot>
but the protocol doesn't involve a "start" phase, I think
18:14
<devsnek>
right
18:16
<rbuckton>
Sure, but depending on .return to close upstream iterators isn't guaranteed either
18:16
<rbuckton>
s/close/"return"
18:17
<Bakkot>
not guaranteed, but it seems very strange to have a builtin which unconditionally prevents you from doing that
18:17
<Bakkot>
rather than deferring to the upstream
18:18
<littledan>
Bakkot: Well, you might think of the first .next() call is more or less a "start" phase
18:20
<akirose>
ryzokuken: working on it. bterlson & robpalme are debugging something
18:20
<Bakkot>
littledan: sure, but I wouldn't really expect that
18:20
<Bakkot>
you can call .return before .next
18:20
<Bakkot>
so it is reasonable to implement an iterator which is opened when it is obtained
18:20
<Bakkot>
not when it is first queried
18:20
<littledan>
right, this case is weird
18:20
<Bakkot>
and the builtins should work with that
18:20
<ryzokuken>
akirose: thanks.
18:21
<littledan>
(I wouldn't expect to have .return/.throw at all, and have previously proposed that we remove all that from the iterator protocol, but maybe it's too late now)
18:21
<devsnek>
there are many more slides
18:21
<rbuckton>
To me its inconsistent to have a built-in that differs in behavior from what a user could normally accomplish with a generator.
18:21
<Bakkot>
whatwg streams make use of them, I think
18:22
<Bakkot>
rbuckton why? generators are a convenient way of creating iterators, but not the only way
18:22
<rbuckton>
Of course, generators are essentially "lazy" since no code runs until the first call to `.next()`.
18:22
<michaelficarra>
jridgewell: it's iterator helpers, not iterable helpers
18:23
<jridgewell>
There's a constructor, no?
18:23
<jridgewell>
`new IterableHelpers(set)`
18:23
<littledan>
Bakkot: I thought that was pretty new/not universally shipped. But iterator .return/.throw has been shipped everywhere for years
18:23
<rbuckton>
michaelficarra: I still think targeting *iterator* and not *iterable* is the wrong abstraction.
18:23
<devsnek>
jridgewell: no
18:23
<ljharb>
rbuckton: every iterator-producing method in the spec already differs in that behavior.
18:23
<Bakkot>
littledan yeah, it's new. seems useful though!
18:23
<devsnek>
jridgewell: set.values().map()
18:23
<ljharb>
ES6 itself wasn't consistent between iterator-producing methods, and "what generators do"
18:23
<Bakkot>
re: "spec will be long", fwiw we could cut down the duplicate spec text the way we do for typed arrays and errors
18:24
<michaelficarra>
jridgewell: no, though there is Iterator.from
18:24
<devsnek>
Bakkot: i tried that, its still very long
18:24
<devsnek>
because each one has very different logic
18:24
<rbuckton>
I would have almost preferred `new Iterable(set.values()).map()`.
18:24
<jridgewell>
Does `Iterator.from` call `@@iterator`?
18:24
<devsnek>
yes
18:25
<michaelficarra>
yep
18:25
<jridgewell>
👍
18:25
<jridgewell>
Removed myself from the queue
18:25
<Bakkot>
devsnek: hm, that's surprising to me
18:25
<devsnek>
Yield macro just calls GeneratorYield or AsyncGeneratorYield
18:25
<devsnek>
no new machinery there
18:26
<Bakkot>
devsnek were you using abstract closures?
18:26
<devsnek>
Bakkot: i considered abstract closures
18:26
<devsnek>
i didn't come up with anything fantastic there
18:26
<Bakkot>
because with abstract closures you would just specify a State record and an abstract closure and .next would just invoke the abstract closure
18:26
<Bakkot>
it's only flatmap which would be more than that, I think
18:27
<devsnek>
i don't want to make something that needs special cases
18:27
<Bakkot>
meh
18:27
<michaelficarra>
I don't hate option 1: is there really a need to forward return/throw?
18:27
<devsnek>
just from a principled perspective
18:27
<rbuckton>
I wrote package that essentially has these helpers over iterables:
18:27
<rbuckton>
```js
18:27
<rbuckton>
const { from } = require("iter-query");
18:27
<rbuckton>
from(set.values()).map(...)
18:27
<rbuckton>
```
18:27
<rbuckton>
It makes a lot more sense to me at that level, though I understand the want to attach these to `%IteratorPrototype%` for convenience.
18:27
<Bakkot>
it's editorial
18:27
<devsnek>
i think we need good ways to add stdlib behaviour
18:27
<devsnek>
without special casing everything
18:27
<Bakkot>
I don't really think we should be optimizing for the spec being short
18:27
<Bakkot>
s/don't really think we should/strongly believe we should not/
18:27
<shu>
agreed
18:28
<rbuckton>
I'm personally a fan of something like Option 1 (or at least, that uses `[@@iterator]`)
18:28
<devsnek>
it's not about being short as much as its about being consistent
18:28
<Bakkot>
as long as the user-observable behavior is consistent, I don't know why we would care that much
18:28
<devsnek>
option 3 is polyfillable btw
18:29
<Bakkot>
michaelficarra it seems important that `.throw` and `.return` forward to the underlying iterators, personally
18:29
<Bakkot>
like `iter().map(x => x)` should be as close as possible to `iter()`
18:29
<devsnek>
option 3 doesn't directly forward but it keeps the state consistent
18:30
<devsnek>
it will call the methods, i mean
18:30
<shu>
what is the difference between 2 and 3 other than editorial?
18:30
<devsnek>
in 2 they are plain objects that are iterators
18:30
<devsnek>
in 3 they are actual generators
18:31
<shu>
ah, but specced using spec machinery instead of JS code?
18:31
<devsnek>
yeah
18:32
<littledan>
personally I like option 3 the best, and agree with this goal of avoiding special-casing.
18:33
<littledan>
(just because we used one-off solutions each time in the past does'nt mean we need to keep doing that forever in the future...)
18:33
<michaelficarra>
I really don't think the presence of the methods should be conditional
18:33
<michaelficarra>
ljharb ^
18:33
<littledan>
+1
18:34
<robpalme>
is bradford on IRC?
18:34
<ljharb>
michaelficarra: i can understand that position for sure. but also APIs that consume iterators might be checking for the presence of those methods now, and taking simpler code paths when they're absent, so it might have an impact
18:34
<Bakkot>
agreed it might have an effect but I agree with michaelficarra anyway
18:36
<devsnek>
Bakkot: what do you think about async abstract operations
18:36
<devsnek>
abstract closures*
18:37
<Bakkot>
devsnek hmmm
18:37
<Bakkot>
no inherent problem with them I guess
18:37
<Bakkot>
would need to be defined
18:37
<ljharb>
from outside, it'd just be a regular one that returned a promise
18:37
<ljharb>
seems fine to me also
18:37
<shu>
no, more than that
18:37
<shu>
but that part of the spec could use our going over anyhow
18:38
<shu>
the part that actualy does the continuation wrapping in a promise
18:38
<devsnek>
it would definitely require spec work
18:39
<rbuckton>
I still wish the helpers went through `[@@iterator]` so they could be copied to other objects that are iterable. For all built-in iterators as well as generators, `[@@iterator]()` just returns `this`. Just depending on the presence of a `next` method makes me think of all of the issues with `then` we've had in the past.
18:40
<ljharb>
shu: i know it'd need lots more for "inside" the async abstract closure - i meant like from the callsites
18:40
<michaelficarra>
unfortunately I don't think we're going to come to a clear decision before this timebox is over :-(
18:40
<devsnek>
rbuckton: the main concern is preventing people from getting into patterns that rely on @@iterator being reusable when it isn't
18:40
<keith_miller>
ystartsev: Wait so would something like Symbol.generatorInitialize solve option 1?
18:41
<devsnek>
what is Symbol.generatorInitialize
18:41
<keith_miller>
that is called when the generator function is first called
18:41
<brad4d>
robpalme sorry got dropped
18:41
<devsnek>
to validate args and stuff?
18:41
<brad4d>
what were you asking me?
18:41
<ljharb>
keith_miller: how would i do that syntactically tho with regular generators
18:41
<keith_miller>
yeah
18:41
<ystartsev>
ping jorendorff for that
18:41
<ystartsev>
pinging*
18:42
<keith_miller>
You'd have to have something like (function* myGenerator() { ... })[Symbol.initializeGenerator] = function init() { validate(arguments[0]); }
18:42
<keith_miller>
not saying it's pretty
18:43
<keith_miller>
ljharb: but it would let you do stuff
18:43
<ystartsev>
oh no that wouldn't solve it actually
18:43
<ljharb>
at the risk of making all calling of generators slower?
18:43
<keith_miller>
Ah, ok
18:43
<ystartsev>
because you wont be able to forward properly
18:43
<Bakkot>
I think you just write a function which invokes and generator and returns it
18:43
<keith_miller>
ystartsev: the initialize could set up the forwarding
18:44
<Bakkot>
function f(){ validate(); return function*(){}(); } or whatever
18:44
<keith_miller>
ljharb: I mean initializing generators is already crazy slow
18:44
<keith_miller>
lol
18:44
<devsnek>
that's what option 3 does
18:44
<Bakkot>
right
18:44
<Bakkot>
and I think userland code would do the same thing if they want this
18:44
<devsnek>
yep
18:44
<keith_miller>
would do this?
18:44
<keith_miller>
Or would make their equivalent of the polyfill?
18:44
<devsnek>
well actually what i want is a way to create a generator that has no initial yield
18:45
<keith_miller>
I mean sure, this is just a hacky way to get that
18:45
<jridgewell>
I don't think complicating generator functions even more is a good solution to this
18:45
<devsnek>
oh no i don't think we should do that as part of this
18:45
<devsnek>
none of these options ask for that
18:46
<keith_miller>
I mean option 3 is effectively asking VMs to do it
18:46
<jridgewell>
Options 2 and 3 seem to be regular functions that could return generator instances, which seems a better solution
18:46
<keith_miller>
so... for me there's no difference but I'm an implementor
18:47
<jridgewell>
Giving more magic to generator functions makes the transform muchhh more complicated
18:47
<devsnek>
did we get consensus to use option 3 there?
18:47
<jridgewell>
I already don't want to maintain the regenerator transform
18:48
<ystartsev>
we didn't really get a conclusion here right?
18:48
<devsnek>
yeah that was weird
18:48
<michaelficarra>
wow how did we get this far down on the agenda?
18:48
<michaelficarra>
time constraints?
18:48
<devsnek>
afaik the point of that presentation was to get consensus on how we should proceed
18:48
<haxjs>
I'm not sure how option 3 forward the arg of first next call (which function.sent need)?
18:49
<devsnek>
haxjs: StartIteratorHelper calls .next() once
18:49
<devsnek>
which is why %SyncMap% starts with a Yield()
18:51
<haxjs>
Can't find it in https://gist.github.com/jorendorff/35504c2553170be98fc2810ccf60c608 🤔
18:51
<devsnek>
haxjs: the value is lost there
18:51
<devsnek>
that's not option 3
18:51
<jridgewell>
That's Option 1, I think
18:52
<haxjs>
Iterator.prototype = {
18:52
<haxjs>
map(mapper) {
18:52
<haxjs>
let it = SyncMap(this, mapper);
18:52
<haxjs>
it.next();
18:52
<haxjs>
return it;
18:52
<haxjs>
}
18:52
<haxjs>
};
18:52
<devsnek>
haxjs: more or less, yeah
18:56
<ystartsev>
re: iterators
18:56
<ystartsev>
i have opened this issue: https://github.com/tc39/proposal-iterator-helpers/issues/97
18:56
<ljharb>
keith_miller: re your queue item; they already can't, because they're inside an expression position
18:56
<keith_miller>
ljharb: ??
18:57
<keith_miller>
I'm saying it's the same result as an eval
18:57
<ystartsev>
do you all think we could revisit this for 5 min on thursday?
18:57
<ljharb>
keith_miller: ah, k
18:59
<ljharb>
brad4d: an IIFE wouldn't necessarily preserve `super`, `arguments`, `this`; nor `await`, and it would make control flow questions complicated
19:01
<brad4d>
an arrow iife preserves `super`, `this`, `arguments`
19:01
<brad4d>
is it really desirable to return / break from a do {} expresssion?
19:01
<devsnek>
yes
19:01
<ljharb>
imo no, but some folks think yes
19:01
<jridgewell>
Arrow won't preserve `yield`
19:01
<ljharb>
or `await`
19:02
<devsnek>
i really want control flow from do expressions
19:02
<jridgewell>
You can use `await async () => { await x }`
19:02
<shu>
bradleymeck: control flow non-local to the do block is contentious
19:02
<jridgewell>
But not for `yield`, because we still don't have arrow generators
19:04
<bradleymeck>
shu: did you mean to ping me on that?
19:05
<shu>
bradleymeck: nope, sorry :)
19:05
<shu>
brad4d: ^
19:05
<brad4d>
shu ack
19:07
<bradleymeck>
i think control flow has utility in various positions that are annoying to deal with otherwise but not fatal to be missing
19:10
<bradleymeck>
there are some really odd things you can do though, like `do {continue}` on a destructuring default assignment to skip a loop
19:12
<ljharb>
does return/break/continue inside eval already work in an expression position?
19:12
<devsnek>
no
19:12
<brad4d>
you mean `let {x = do {continue}} = obj;` would continue a loop if `obj` doesn't have an `x`?
19:12
<brad4d>
I think that is harmful to readability.
19:13
<devsnek>
to me that's a linting concern
19:13
<devsnek>
there are places (outside of destructuring declarations) where continue can be useful
19:14
<akirose>
that's how zkat initially wrote those proposals iirc—pattern matching + do expressions intended to move through committee side-by-side
19:14
<brad4d>
devsnek could you point me at a use-case where flow-control inside a `do{}` would be beneficial? I can't seem to come up with one on my own?
19:14
<leobalter>
ljharb: the coupling with pattern matching would be a nice thing to discuss in incubator(ish?) calls
19:15
<leobalter>
idk Mark's irc handler if any
19:15
<ljharb>
leobalter: agreed; we're still pretty far from being ready for that tho (mpcsh)
19:15
<rkirsling>
it's been discussed in the pattern matching calls
19:15
<devsnek>
brad4d: there was one in the slides
19:15
<jridgewell>
Lol
19:16
jridgewell
sees myself to TDZ
19:16
<mpcsh>
ljharb leobalter Bakkot: should we try to get both of these proposals on an incubator call?
19:16
<ljharb>
leobalter: happy to invite you to the next pattern matching call if you're interested
19:16
<leobalter>
yes, please
19:16
<ljharb>
mpcsh: yes, but i think after i've got the PR ready to update the proposal :-)
19:17
<mpcsh>
👍
19:18
<rbuckton>
I've seen a fair amount of Kotlin code that does continue/break/return in expression positions:
19:18
<rbuckton>
```kotlin
19:18
<rbuckton>
for (x in list) {
19:18
<rbuckton>
val y = x?.y ?: continue;
19:18
<rbuckton>
...
19:18
<rbuckton>
}
19:18
<rbuckton>
```
19:19
<jridgewell>
There's a goog internal server language that has `or exit` all over the place.
19:19
<littledan>
I share Bakkot 's intuition about blocking return, continue and break from expressions breaking some kind of invariant that we have
19:19
<rkirsling>
rbuckton: I don't think it'd be contentious without the visible boundary of `do {}`
19:19
<littledan>
so, I guess this is what exceptions are for?
19:19
<ljharb>
same; flow control doesn't belong in expression position
19:20
<rbuckton>
rkirsling: which wouldn't be contentious? `x?.y ?? continue` or `x?.y ?? do { continue; }`?
19:20
<devsnek>
there is no such invariant in how we have specified the language
19:20
<devsnek>
in fact completion values help allow it
19:20
<ljharb>
devsnek: sure, i didn't say they can't be. i said they shouldn't be.
19:21
<devsnek>
dan said there was an invariant
19:21
<devsnek>
which i strongly disagree on
19:21
<ljharb>
oh
19:21
<ljharb>
well, the invariant is that you currently can't do any non-throw flow control in expression position
19:21
<rkirsling>
rbuckton: the former wouldn't be, is my argument. "everything is an expression" doesn't induce confusion where "crossing the border between worlds" does
19:21
<ljharb>
it may or may not be intentional, but it remains an invariant
19:21
<leobalter>
I'm totally +1 to do expressions. Although, a spec draft would make it easier for an overview
19:22
<littledan>
hmm, I'm not sure why you'd have to care so much about the microtask ticks... I'd hope not many developers have to think in those terms
19:22
<ljharb>
people often think about overhead
19:22
<littledan>
devsnek: Well, it's currently an invariant; we can disagree about the priority of preserving it
19:22
<littledan>
like, it's currently a fact about JS that that doesn't happen
19:23
<devsnek>
that's not an invariant its just a hole
19:23
<rbuckton>
rkirsling: I have an issue on the do-expressions repo that suggests dropping `do {}` and updating ParenthesizedExpression to allow most statements. Then you would have `x ?? (continue)`. The parens are necessary to preserve precedence of `,`, which was one of Bakkot's concerns about throw expressions.
19:23
<littledan>
the JS spec notation allows all kinds of stuff that we have decided we won't do
19:23
<devsnek>
that's like saying %Iterator%.prototype.map not existing is an invariant of the language
19:23
<ljharb>
and indeed, it is right now
19:23
<littledan>
so, in general, I think that assertions of things being "invariants" are value judgements, and I'm comfortable calling my claim a value judgement
19:23
<ljharb>
devsnek: but i think there's a categorical difference there that you surely are aware of
19:23
<littledan>
it's a statement about what we want in the future
19:24
<ljharb>
drousso: what about the dev tools/repl?
19:24
<devsnek>
value judgement seems like a better term
19:24
<drousso>
ljharb i don't think those people think of that as "completion"
19:24
<rkirsling>
I'm confused by the non-specific confusion
19:24
<ljharb>
drousso: and yet that's what it is
19:24
<ljharb>
drousso: so would it be more palatable if do expressions were explained as "like in the dev tools"?
19:25
<rkirsling>
the goal is to continue preserving "ignorance is bliss" around completion values, was my understanding
19:25
<ljharb>
drousso: since that's something virtually every dev already understands?
19:25
<drousso>
ljharb im not convinced that developers even know what's going on in the console
19:25
<ljharb>
drousso: they figure it out very quickly. they type `3` and the result is `3`
19:25
<ljharb>
or `if (true) { 3 }` and the result is `3`
19:25
<drousso>
it doesn't work exactly like the devtools tho
19:25
<devsnek>
i just don't get like
19:26
<ljharb>
drousso: aside from "devtools exposes internals" and whatnot, how does it differ?
19:26
<devsnek>
why can't we just say some people don't like control flow there, and leave it to linters
19:26
<drousso>
oh wait i was thinking of something different
19:26
<drousso>
yes it does work the same as devtools
19:26
<drousso>
i don't think that that's a good way of explaining it though
19:27
<drousso>
as that doesn't clarify anything about what's happening
19:27
<drousso>
it just provides a "if you want to see it in action, use devtools"
19:27
<drousso>
it doesn't explain what's actually happening
19:27
<drousso>
s/it/devtools
19:27
<ljharb>
drousso: the explanation isn't needed tho, if everyone already intuits how it's supposed to work
19:27
<robpalme>
Younies is unavailable for his presentation so Record & Tuple is next.
19:27
<drousso>
i disagree with that
19:27
<drousso>
vehemently
19:28
<rkirsling>
can you give specific examples of what the people you spoke to thought the basic cases should do instead?
19:28
<drousso>
the function declaration
19:28
<haxjs>
+1 for banning too :)
19:29
<drousso>
many i spoke to thought that that would result in the function declaration being used
19:29
<littledan>
I disagree with the notion that a proposal like this would need to add new capabilities (like return/break/continue from an expression) to carry their own weight; I'm not sure if waldemar was alluding to that
19:29
<devsnek>
waldemar said this proposal isn't worth it without control flow
19:29
<Bakkot>
drousso you get a syntax error; I think "what does this code do? oh it's a syntax error" is not that big of a deal
19:29
<haxjs>
I think many devs only want some sugar for IIFE.
19:29
<devsnek>
i certainly won't use it as much as i was planning to without control flow
19:30
<ljharb>
haxjs: why does that mean they shouldn't get it?
19:30
<drousso>
i don't think syntax errors are a good way of teaching a developer how to use something
19:30
<drousso>
in fact i've spoken with many developers who find JS errors often unhelpful
19:30
<devsnek>
that's more on engines
19:30
<ljharb>
unfortunately we don't specify error messages, that's on the browsers
19:30
<ljharb>
* browsers/engines
19:31
<devsnek>
engines don't even bother to implement parsers which support reporting multiple errors
19:31
<ystartsev>
drousso: we had pretty strong support internally for this, its interesting that your front end developers have such a strong issue with this. Are there certain patterns that they are using that makes it more difficult?
19:31
<haxjs>
ljharb so any other capabilities just add confusion even they are powerful :)
19:31
<ystartsev>
and also, yes -- engines cannot really improve their error messages due to web compat
19:31
<ljharb>
haxjs: i agree that return/continue/break in do expressions are powerful and also add confusion, yes
19:31
<drousso>
that is true
19:31
<ystartsev>
we tried and had to back it out
19:31
<drousso>
im not saying that's the fault of this situation
19:31
<drousso>
or that it's up to this proposal to fix it
19:32
<drousso>
just that i believe errors are not a good way to teach things
19:32
<drousso>
brad4d +1000
19:32
<ljharb>
drousso: i think it's very unlikely devs will even try to do these things in the first place tho
19:32
<drousso>
brad4d completely agree
19:32
<ljharb>
drousso: iow, i think that most devs won't ever run into it.
19:32
<drousso>
ljharb if that's the case, why add it in the first place?
19:33
<rkirsling>
I will say that I too originally expected that `return` would serve as an early out _for the do expr_
19:33
<drousso>
or wait do you mean these "edge cases" or `do` in general?
19:33
<ljharb>
drousso: because they *will* try to use all the non-error cases in a block in expression position
19:33
<ljharb>
drousso: i mean the edge cases
19:33
<ljharb>
drousso: tons of people will immediately try to use the non-edge-cases in a ton of code
19:33
<rkirsling>
(but obviously it's moot if it's banned)
19:33
<ljharb>
drousso: especially in the react community inside jsx, not that i think that needs to be a motivation
19:33
<ljharb>
rkirsling: well, i'm saying i don't think they'll even run into the bans
19:34
<ljharb>
rkirsling: i think most users won't ever discover those are missing because they'll never think to try it
19:34
<haxjs>
But, I also think banning everything controversial not really solve the problems, for example how can we break a loop and return a value (it seems it will be banned as slide)
19:34
<ljharb>
haxjs: same way you do now: return a sentinel value, and then check it in the main loop body
19:35
<rbuckton>
Back when I presented throw expressions I was asked by many in the committee to investigate converting other statements to expressions, especially `return`, `continue`, `break`. I'm actually surprised at the number of people in favor of banning those statements in a `do {}` expression.
19:35
<ystartsev>
re: iterator helpers issue: https://github.com/tc39/proposal-iterator-helpers/issues/97
19:35
<ystartsev>
please comment so we can get to a solution!
19:35
<devsnek>
ljharb: no right now you just `return`
19:35
<haxjs>
ljharb: so i guess dev would expect iife which can return a value directly :-P
19:35
<devsnek>
if anything not allowing control flow is a refactoring hazard
19:35
<ljharb>
devsnek: not if the value comes from an IIFE, or another function
19:36
<ljharb>
haxjs: they'll expect their do expression body to be able to produce a value; i'm saying they won't expect it to be able to force the containing function to return
19:37
<brad4d>
@devs
19:37
<brad4d>
devsnek allowing flow of control is a refactoring hazard if you're inlining a function
19:39
<brad4d>
`do{}` expressions would make function inlining much easier if they really act like inline functions
19:39
<haxjs>
ljharb: what I'm talking is code like `do { while(...) { if (...) { 1 ; break } } }`
19:40
<ljharb>
haxjs: that would work fine, because the loop you're breaking is fully inside the `do`
19:40
<ljharb>
haxjs: i think
19:40
<ljharb>
haxjs: ohh right but it wouldn't because of ending in a loop
19:40
<ljharb>
haxjs: so then `do { let v; while (…) { if (…) { v = 1; break; } } v; }`
19:41
<haxjs>
yeah, this is why i say devs may like iife sugar...
19:42
<ljharb>
gotcha, agreed
19:43
<ljharb>
well, i see what you mean anyways. i don't think they actually want a function invocation
19:43
<haxjs>
As i understand, basically current minimal proposal just have very similar power or even less power of iife.
19:43
<ljharb>
and less overhead
19:44
<haxjs>
yeah, so maybe iife sugar is what we need?
19:44
<Bakkot>
current proposal lets you do something you can't with IIFE, which is await/yield
19:45
<Bakkot>
await you can do with a microtask tick, yield... you just can't do, I think, at least without a bunch of wrappers
19:45
<ljharb>
^ that
19:45
<haxjs>
yeah! so it's iife + await async iife sugar :-P
19:46
<Bakkot>
bterlson/other chairs: voice jorendorff ?
19:47
<sffc>
I'll figure out my mic
19:47
<sffc>
go to the next speaker
19:49
<sffc>
I'll follow up on GitHub and/or in the hallway track
19:50
<ystartsev>
Bakkot: on it
19:52
<jorendorff>
thank you
19:55
<Bakkot>
complex numbers don't have -0, bah
19:56
<jorendorff>
haha
19:57
<Bakkot>
during the editor update I misspoke: it's actually caiolima doing the work to fix the number types in the spec. mea culpa.
19:58
<leobalter>
time is over for today, but we have someone logged in as Guest in the call, I believe we should avoid that tomorrow.
19:58
<rkirsling>
indeed
20:03
<leobalter>
SameValue makes sense if we want to follow pattern with `includes`, right?
20:04
<jorendorff>
well ... it seems more directly applicable to look at what `===` does, than `includes`
20:04
<Bakkot>
leobalter SameValueZero, technically
20:05
<Bakkot>
`[-0].includes(0)` and `[NaN].includes(NaN)` are both true
20:06
<mpcsh>
I am opposed to shortening lunch, for the record. the hallway-track social time is nice
20:08
<rkirsling>
mpcsh: I don't think we necessarily need to decrease break time, perhaps just rearrange it
20:08
<sffc>
Ujjwal and I are in the hallway track; would be nice to have more
20:09
<haxjs>
I feel we should keep consistency with normal `===`. The weirdness of `===` is coming from IEEE float, developers are inevitable to learn it, add an exception rule for tuple/record just make things worse and never really solve anything.
20:09
<sffc>
I have some thoughts about Record/Tuple that I'd like to discuss with the champions
20:10
<akirose>
did we fall back to hubs?
20:10
<ystartsev>
lets use online town for today
20:10
<akirose>
kk
20:10
<ystartsev>
and tomorrow switch to hubs
20:10
<ystartsev>
online town has some issues with distance that hubs didnt
20:10
<bradleymeck>
i think having any value fail to ever be === if a sub component is NaN is... highly surprising
20:12
<rickbutton>
sffc: do you want to chat now? I'm free, or via email?
20:13
<sffc>
I'm in the town, plus 5 others now
20:13
<rickbutton>
oh right
20:13
<rickbutton>
will be there shortly
20:14
<bterlson>
Chairs discussed shorter lunch break and we will stick with 1 hour for now. Delegates with free time should consider joining us in the hallway track! /cc Bakkot
20:14
<leobalter>
akirose bterlson how hard would it be to change my initials in the notes? I'd rather go with LFB (to reflect my actual initials), but I don't wanna cause too much work
20:14
<mpcsh>
leobalter: I switched mine from MCN to MPC a little while ago, it's not bad
20:15
<mpcsh>
just do a find & replace for today's notes, and submit a PR for old notes
20:19
<TabAtkins>
Bakkot: How are complex numbers avoiding -0?
20:25
<Bakkot>
TabAtkins the traditional definition of complex numbers does not include two distinct 0s
20:26
<Bakkot>
(or four, I guess)
20:26
<TabAtkins>
Well sure, but the traditional definition of the reals doesn't either.
20:26
<TabAtkins>
Complex-in-JS would probably have some -0s in it
20:27
<TabAtkins>
(Probably... 3? If they're just a pair of Numbers.)
20:28
<Bakkot>
0,0, -0,0, 0,-0, -0,-0 is four
20:28
<Bakkot>
I guess just three -0s though
20:28
<TabAtkins>
0,0 is a positive zero, yeah ^_^
20:32
<ljharb>
jorendorff: hopping into the hallway track if you wanted to chat now
20:33
<jorendorff>
@Bakkot believe it or not I think Brendan Eich exposed -0 to JS based on advice from Guy Steele that had to do with complex numbers
20:33
<Bakkot>
does css have a -0 which is observably different from 0?
20:33
<Bakkot>
jorendorff fascinating
20:33
<jorendorff>
in my hearing he only ever explained it far too fast for me to follow
20:34
jorendorff
looks for the hallway-track link
20:34
<Bakkot>
it's in the reflector I think
20:34
<shu>
"far too fast": checks out for brendan!
20:37
<jorendorff>
got it
20:39
<TabAtkins>
Bakkot: CSS grew a -0 that is *slightly* observable, to preserve IEEE semantics and JS compatibility. It gets censored into a plain zero the moment is would escape a math function.
20:39
<TabAtkins>
But yeah, `margin-left: calc(1/0);` is different from `calc(1/-0)`.
20:43
<Bakkot>
good times
20:43
<Bakkot>
-0 was a terrible idea
20:43
<Bakkot>
I will die mad about that
20:44
<jorendorff>
can't wait for some brave new language to just say no
20:46
<shu>
what... do i do for the rest of my day
20:46
<ljharb>
Bakkot: but how else can i express the limit of an integral approaching zero from the negative direction
20:46
<TabAtkins>
Oh jeez I forgot it was 3pm Central, I was waiting for the meetig to start again
20:46
<TabAtkins>
ljharb: OH easy, don't
20:47
<ljharb>
my calculus teacher would be horrified
20:47
<Bakkot>
ljharb: 0
20:47
<rickbutton>
shu: sleep
20:47
<Bakkot>
how do you express the limit of an integral approaching 1 from the negative direction? :P
20:48
<ljharb>
touché
20:49
<jorendorff>
ljharb: suppose we go with option 2, to me the most obvious way to do that would be different iterator types for map, filter, take, drop, etc.
20:49
<jorendorff>
ljharb: so, different internal slots for each
20:49
<jorendorff>
and every method has a brand check
20:50
<rkirsling>
Bakkot: +1 re -0
20:51
<rkirsling>
so many NaNs and yet two zeroes is too many
20:51
<rkirsling>
*two 0s
20:52
<ljharb>
jorendorff: sure, seems right to me
20:52
<ljharb>
jorendorff: altho it also seems doable as a single object type
20:52
<jorendorff>
ljharb: ok, right, I'm thinking about that now
20:53
<ljharb>
it might get weird with some of the types tho
20:53
<jorendorff>
they do all have something in common, which is that they all have a single source iterator... except there's `Iterator.prototype.flatMap()`, the sole exception
20:53
<ljharb>
that doesn't have a source iterator? or it has multiple
20:53
<ljharb>
(those were questions, not statements)
20:54
<Bakkot>
I think you'd have an abstract op which returned a list of values to yield, and everything except flatmap would return a list of length exactly 1
20:54
<Bakkot>
boom, no more special case
20:55
<jorendorff>
ok, so if we do this, we can have a common implementation of throw and return shared by all the iterator helpers
20:55
<jorendorff>
the common thing needs a name
20:55
<ljharb>
and the common thing would just be "innerIterator?.return()` etc?
20:55
<Bakkot>
if they're different objects, the common thing would be spec-internal, right?
20:55
<jorendorff>
Bakkot: wait, actually I didn't follow that
20:55
<Bakkot>
so the name doesn't matter so much
20:55
<ljharb>
or sorry `innerIterator.return?.()`
20:55
<Bakkot>
IteratorHelperReturn or whatever
20:56
<jorendorff>
Bakkot: "abstract op which returned a list of values to yield" I don't understand when this abstract op is used
20:56
<jorendorff>
I... don't think I understand this scheme at all actually
20:57
<Bakkot>
jorendorff the idea is that each helper would define such an abstract op, and the `next` would know how to invoke the abstract op
20:57
<Bakkot>
we can talk about it more tomorrow
20:57
<Bakkot>
hard to talk about it without code
20:57
<jorendorff>
ok, and the helper would have abstract ops for `throw` and `return` too?
20:58
<Bakkot>
the helper would specifically be the implementation of `.next`
20:58
<Bakkot>
but yeah maybe?
20:58
<Bakkot>
not sure
20:58
<Bakkot>
have to write it out
20:59
<jorendorff>
ok, let's meet up tomorrow and talk about it more, maybe sketch some things out?
20:59
<Bakkot>
y
20:59
<jorendorff>
ljharb: are you free tomorrow afternoon at 2PM Pacific time to chat?
20:59
<devsnek>
return/throw may also have to touch logic in the helper itself
20:59
<devsnek>
which is why i mentioned that it isn't ideal to have them just be methods that call the inner iterator
21:00
<ljharb>
jorendorff: yep, works for me
21:00
<Bakkot>
devsnek what logic in the helper do they need to touch?
21:00
<devsnek>
idk
21:00
<Bakkot>
other than "mark as stale", I guess
21:00
<devsnek>
flatMap is one
21:00
<jorendorff>
ljharb: thanks very much, let's all meet here 2PM Pacific tomorrow, then we'll set up a video chat
21:01
<devsnek>
there could be more in the future
21:01
<jorendorff>
I think flatMap is the only one; the others all do the same thing for throw (forward it) and return (forward it0
21:01
<jorendorff>
right, the only one at present
21:01
<Bakkot>
what does flatmap need to do specially?
21:01
<devsnek>
close two iterators
21:01
<Bakkot>
ah, yeah, sure
21:01
<devsnek>
we could have more in the future
21:01
<jorendorff>
flatmap is `for (let iterable in this) for (let value in iterable) yield value;`
21:02
<devsnek>
i'd rather do the work now to have a proper way to specify generators in our stdlib
21:02
<devsnek>
than keep having to make weird iterator things forever
21:02
<Bakkot>
I kind of prefer making weird iterator things forever, even if we had a proper way to specify generators
21:02
<jorendorff>
If the goal is to produce a common type of iterator that shares some implementation details with other iterators, with common throw/return methods,
21:02
<Bakkot>
ease of spec isn't really a priority
21:03
<devsnek>
i want consistency
21:03
<devsnek>
of how our systems behave
21:03
<jorendorff>
that doesn't expose implementation details,
21:03
<Bakkot>
weird iterator things forever is the consistent thing
21:03
<jorendorff>
...then the exact thing we are talking about as an ideal end state is... a generator
21:03
<devsnek>
^
21:03
<Bakkot>
right, if that's the goal
21:03
<jorendorff>
I agree weird iterator things forever is consistent with existing practice
21:03
<Bakkot>
I don't really share that goal
21:03
<Bakkot>
I don't object to it, but don't see why it's valuable
21:04
<jorendorff>
ease of spec is not what I'm concerned with
21:04
<devsnek>
i don't want generators for the sake of generators, i want them because they handle all the reentrancy and cleanup and whatnot properly
21:04
<jorendorff>
ease of using and understanding the spec matters to me
21:05
<devsnek>
i'm more concerned with ease of understanding but i also have to write all these methods so...
21:05
<jorendorff>
anyway -- we should talk more tomorrow. thanks again for your time
21:06
<jorendorff>
Bakkot: oh, btw - you mentioned today that you don't think programmers will try to use break/return from within do-expressions
21:07
<devsnek>
i feel like half of all js code is early returns
21:07
<jorendorff>
Bakkot: i think they will :( because there are lots of expression languages, most notably Ruby and Rust but I think it's not even uncommon these days
21:08
<Bakkot>
jorendorff did not mean to imply that
21:08
<jorendorff>
expression languages that have weird control flow stuff like `return`
21:08
<jorendorff>
(Smalltalk too)
21:08
<Bakkot>
I think people won't try to end their do-exprs with declarations
21:08
<Bakkot>
and yeah I've used the feature in ruby
21:08
<Bakkot>
and rust
21:08
<jorendorff>
oh, that I agree we can just call it a SyntaxError
21:09
<jorendorff>
my comment is limited to break/continue/return
21:09
<Bakkot>
yeah, like I say I didn't mean to imply people won't try that
21:09
<Bakkot>
if I did say that i misspoke
21:09
<jorendorff>
i probably misheared, i don't mean to put words in your mouth!
21:10
<rbuckton>
The TypeScript source heavily utilizes function declarations that trail the source code that uses them. I could see function declarations at the end of a `do {}` tripping people up if they're refactoring.
21:10
<Bakkot>
sounds like a good reason for that to be a syntax error!
21:10
<Bakkot>
if some people are actually going to expect to get the before-declaration value
21:10
<rbuckton>
No, that still would trip them up.
21:10
<Bakkot>
instead of the function itself
21:11
<rbuckton>
it would be better if function declarations don't contribute to the resulting value
21:11
<Bakkot>
People getting tripped up on things being a syntax error is the least bad kind of people getting tripped up.
21:11
<Bakkot>
Strong disagree.
21:11
<jorendorff>
agree with "least bad"
21:11
<Bakkot>
if `do { 1; function f(){} }` results in `1` and not a function, that's... not... correct
21:11
<rbuckton>
why do you disagree?
21:11
<ljharb>
yeah that'd be more bad
21:11
<sffc>
@chairs - can you inform the delegates of the decision of lunch break duration before tomorrow, so that I can adjust my schedule accordingly? I'm trying to fit in non-TC39 meeting during the lunch break.
21:12
<rkirsling>
definitely more bad
21:12
<rbuckton>
To me that argues for explicit syntax for the return value.
21:12
<Bakkot>
sffc bterlson said above they will stick with 1 hour
21:12
<sffc>
I have a slight preference for 60-minute break because of that reason (ability to schedule a meeting during prime time)
21:12
<Bakkot>
rbuckton how so?
21:12
<Bakkot>
You can get the return value you want by putting an expression as the last statement.
21:12
<bterlson>
sffc: confirm, 1 hr lunch will continue
21:13
<Bakkot>
and putting a declaration as the last statement gives a syntax error
21:13
<sffc>
Sounds good, thanks
21:13
<Bakkot>
so you can do the things you want, and the surprising cases you can't run into
21:13
<jorendorff>
Bakkot: separate weird comment: `yield` expressions can already return ... you just ... don't have any control over it
21:13
<rbuckton>
Having to move the function is a mess WRT refactoring tooling
21:13
<ljharb>
or at least, you'll run into them immediately at dev time
21:14
<Bakkot>
jorendorff yeah I was avoiding bringing that up
21:14
<jorendorff>
I'm not sure what to conclude from that
21:14
<Bakkot>
it is true but obscure and also very strange
21:14
<jorendorff>
probably for the best
21:14
<devsnek>
i would conclude that making rules about what can occur in do expressions is dangerous
21:14
<jorendorff>
i mean, it means that the spec-internal wiring
21:14
<Bakkot>
rbuckton but at least you get an error instead of the wrong thing!
21:14
<Bakkot>
so you know your refactor needs to change
21:14
<rbuckton>
Consider this code:
21:14
<rbuckton>
```js
21:14
<rbuckton>
const fn = (x) => {
21:14
<rbuckton>
// 1
21:14
<rbuckton>
return x.map(visit);
21:14
<rbuckton>
// 2
21:14
<rbuckton>
function visit(y) { ... }
21:14
<rbuckton>
};
21:14
<rbuckton>
const a = fn(b);
21:14
<Bakkot>
seems fine to me
21:14
<rbuckton>
```
21:14
<rbuckton>
If I use tooling to inline `fn` as a `do` expression, the tooling would have to move `visit`, but does it also move `// 2` with it?
21:14
<jorendorff>
for returning from an expression, already exists and works
21:15
<Bakkot>
rbuckton probably yes; most tooling considers comments to attach to the following statement, which is decent heuristic
21:15
<Bakkot>
rbuckton but also I don't think "tooling which is automatically rewriting code will need to make a call about how to handle comments" is an argument which should have much weight
21:16
<rbuckton>
```
21:16
<rbuckton>
const fn = (x) => {
21:16
<rbuckton>
// 1
21:16
<rbuckton>
return x.map(visit);
21:16
<rbuckton>
// long explanation of what visit does
21:16
<rbuckton>
// even more text...
21:16
<rbuckton>
function visit(y) { ... };
21:16
<rbuckton>
};
21:16
<rbuckton>
```
21:16
<ljharb>
comment attachment is definitely already an intractable problem imo
21:16
<Bakkot>
tooling usually considers all of the comments between statement A and statement B to be attached to B, unless they occur at the end of line A, in my experience
21:16
<ljharb>
rbuckton: if `visit` requires that much explanation, then why isn't it extracted into a separate tested module?
21:16
<Bakkot>
so the long explanation would get moved
21:16
<rbuckton>
I disagree, tooling is an important consideration, which is why there's a monthly tooling call
21:17
<Bakkot>
I agree that tooling is important.
21:17
<devsnek>
how about if do expressions allows control flow i'll write the eslint rule to disallow it for you
21:17
<Bakkot>
I disagree with the specific claim that "tooling which is automatically rewriting code will need to make a call about how to handle comments" is an argument which should have much weight
21:17
<Bakkot>
that is more specific than "tooling".
21:18
<ljharb>
devsnek: first you'd have to convince eslint core to add the rule, under their new rules policy
21:19
<devsnek>
what's that policy
21:19
<Bakkot>
devsnek I will continue having to read other code bases
21:19
<Bakkot>
more to the point, so will everyone else
21:19
<devsnek>
and they will read my beautiful code that uses control flow
21:19
<devsnek>
and say "wow bakkot's code is lacking in this amazing pattern"
21:19
<devsnek>
:P
21:19
<Bakkot>
they will read your code that uses control flow
21:19
<Bakkot>
that part I agree with
21:20
<Bakkot>
devsnek the policy is that they do not accept rules which just ban syntax, if you could write it with the forbidden syntax rule
21:20
<rbuckton>
Comparison:
21:20
<rbuckton>
```
21:20
<rbuckton>
// no cf
21:20
<rbuckton>
for (const x of ar) {
21:20
<rbuckton>
const y = x.y;
21:20
<rbuckton>
if (y === null || y === undefined) continue;
21:20
<rbuckton>
...
21:20
<rbuckton>
}
21:20
<rbuckton>
// with cf
21:20
<rbuckton>
for (const x of ar) {
21:20
<rbuckton>
}
21:21
<rbuckton>
```
21:21
<rbuckton>
// with cf
21:21
<rbuckton>
for (const x of ar) {
21:21
<rbuckton>
const y = x.y ?? do { continue; }
21:21
<rbuckton>
}
21:21
<rbuckton>
```
21:21
<Bakkot>
rbuckton that example does not make me want to allow control flow
21:21
<rbuckton>
oi (code fragments in irccloud can be a pain)
21:21
<shu>
why is that better?
21:21
<shu>
rbuckton: yeah i may be having the opposite reaction you want
21:21
<shu>
rbuckton: which is that with cf is less readable
21:21
<shu>
i agree that it's terser
21:21
<ljharb>
i agree with that ^
21:22
<shu>
and the === null || === undefined is contrived
21:22
<shu>
if the intention is to test for nullish, == undefined is fine
21:22
<rbuckton>
shu: Its concise, same reason we have `??` now instead of `x !== null || x !== undefined ? x : y`
21:22
<rbuckton>
`== undefined` is not fine because of `document.all`
21:22
<shu>
rbuckton: that concision did not cross statement/expression boundaries
21:22
<shu>
rbuckton: fair enough for document.all
21:23
<Bakkot>
the point about ?? is that it is consise _and clearly expresses intent_
21:23
<Bakkot>
having a `const y =` which is also sometimes a `continue` does not, to me, clearly express intent
21:23
<jorendorff>
no but motivating examples should not be this ... extremely specific
21:23
<rbuckton>
It seems strange to be able to do `x ?? do { throw ... }` but not `x ?? do { continue; }`
21:23
<Bakkot>
why?
21:23
<Bakkot>
expressions can throw, that's normal
21:23
<Bakkot>
expression can't continue
21:23
<Bakkot>
exceptions are exceptional
21:23
<rbuckton>
a statement is a statement.
21:24
<Bakkot>
I don't think that's a distinction users really think about.
21:24
<Bakkot>
`if` is a statement, but does something exprsesions can do
21:24
<Bakkot>
that's fine
21:25
<shu>
i can sympathize with the desire to check all the boxes for all the statements, even though i disagree
21:25
<shu>
i also have an additional reason to ban, which is i don't really think it's worth either spec authors' time nor implementers' time to work through the corner cases like loop headers
21:27
<Bakkot>
there's a lot of edge cases, yeah
21:27
<rbuckton>
Bad alternative:
21:27
<rbuckton>
```
21:27
<rbuckton>
const sContinue = Symbol();
21:27
<rbuckton>
for (const x of ar) {
21:27
<rbuckton>
try {
21:27
<rbuckton>
const y = x.y ?? do { throw sContinue; }
21:27
<rbuckton>
}
21:27
<rbuckton>
catch (e) {
21:27
<rbuckton>
if (e === sContinue) continue;
21:27
<rbuckton>
throw e;
21:27
<rbuckton>
}
21:27
<rbuckton>
}
21:27
<rbuckton>
```
21:27
<Bakkot>
yeah, people can write bad code if they want
21:28
<shu>
so the desire to have universal availability of statements at least has a caveats that the corner cases need some explanation. we can of course define _something_, but i reckon in the end it'll be more surprising that not. we can selectively ban, but that's an equally careful task to carry out, one that i am not happy to allocate staff to
21:28
<Bakkot>
I don't find "people can use this bad alternative" a good reason to allow a thing
21:28
<Bakkot>
I do not expect people to actually write that in practice
21:28
<Bakkot>
instead of your first non-cf example
21:28
<shu>
you can do arbitrary non-structured control flow if you reloop your code today, is that a reason to add goto?
21:29
<shu>
i mean i would personally love goto
21:29
<rbuckton>
At least with banning we can relax that later if there is enough interest in community. I'm not going to die on the hill of `break/continue/return` in `do{}` as I don't have a strong opinion.
21:29
<jorendorff>
shu: as far as `return` is concerned, I don't think there are necessarily any new corner cases to work through; since `yield` already exists, anything to do with expressions returning has already been sorted
21:29
<shu>
jorendorff: i don't follow
21:30
<ljharb>
rbuckton: i think that you wouldn't be alone in jumping on board an immediate follow-on proposal to relax the ban
21:30
<rbuckton>
shu: The only `goto` I want would be to jump to a specific falling switch case (as in C#).
21:30
<rbuckton>
s/falling/following
21:30
<shu>
jorendorff: mechanically being like return doesn't mean programmers think about them similarly, and my impression is that they're not thought of similarly
21:31
<jorendorff>
shu: was in response to the specific point that it wasn't worth spec authors' or implementors' time to work through special cases
21:31
<rbuckton>
But in C#'s case it's `goto case ...`
21:31
<shu>
jorendorff: ah, okay, and for return you're saying that's not true
21:31
<Bakkot>
jorendorff theere is one new edge case, which is `return` in parameter expressions
21:31
<Bakkot>
but yeah it's not nearly as bad as `break`
21:31
<jorendorff>
Bakkot: fantastic
21:32
<jorendorff>
Bakkot: yield is simply banned there, suggesting the same for return
21:32
<Bakkot>
yeah, it's not too bad
21:33
<rbuckton>
Banning `break`/`continue`/`return` is purely banning syntax. If they weren't banned the existing spec machinery would already cover how their handled. The downside of banning them is that it makes the spec more complex rather than less.
21:33
<ljharb>
rbuckton: i don't think it would? because it could happen from a bunch of new places
21:33
<rbuckton>
You also have to ban break/continue/return in eval in a `do`
21:33
<jorendorff>
i'm not sure the spec says clearly what `for (do {break};;)` ought to do
21:34
<Bakkot>
rbuckton: yeah, part of the reason I'm advocating for just banning `break/continue/return`, instead of e.g. having `return` mean "provide this value from the `do`", as some have suggested, is so that the restriction can be relaxed later if there is enough community and implementor interest and someone works through all the edge cases
21:34
<jorendorff>
rather, i'm not sure it does what we would want
21:34
<Bakkot>
rbuckton they are already banned
21:34
<Bakkot>
you cannot `break` out of an `eval`, even a sloppy direct eval
21:34
<jorendorff>
or return, sads
21:35
<rbuckton>
fair
21:35
<Bakkot>
(presumably for the same reason as I am proposing not to let you `break` out of a `do` :P)
21:36
jorendorff
registers doubt
21:36
<rbuckton>
Bakkot: by that you mean this? `for (...) do { break; }`?
21:36
<rbuckton>
or this: `do { break; /*early exit from the do itself*/ }`?
21:37
<Bakkot>
first one
21:37
<rbuckton>
k.
21:37
<rbuckton>
heh: `do { it: break it; }`
21:37
<Bakkot>
that was one of my examples!
21:37
<Bakkot>
actually slightly more complicated
21:38
<TabAtkins>
...can you `yield` within a parameter expression
21:38
<rbuckton>
banning break/continue is would just be changing how labeled evaluation works, correct? Or are you going to try to make `break`/`continue` syntactically invalid in the grammar?
21:38
<TabAtkins>
Ah, jorendorff seems to be saying they're banned there, ok
21:39
<shu>
rbuckton: i was imagining early error static semantics
21:39
<jorendorff>
i was also imagining EESS
21:40
<devsnek>
banning the control flow in loop headers and function parameters is fine
21:40
<rbuckton>
That's fine, just concerned about grammar complexity.
21:40
<Bakkot>
rbuckton the grammar is already set up not to allow an unlabeled `break` outside of a loop, or a `break l` out side of an `l`
21:41
<Bakkot>
making it so that there are no labels or loops visible to the `do` is actually easier than propagating that information through all expressions
21:41
<Bakkot>
(by a lot)
21:41
<devsnek>
not really
21:41
<devsnek>
you have to explicitly ban it using early errors
21:41
<rbuckton>
The grammar for `do {}`? Because there's no grammar restrictions in the spec: https://tc39.es/ecma262/#prod-BreakStatement
21:42
<devsnek>
or a parameter
21:42
<Bakkot>
devsnek you'd have to explicitly allow it, too
21:42
<devsnek>
no you wouldn't?
21:42
<Bakkot>
there is an early error for `break` outside of loops
21:42
<devsnek>
but not one for break inside blocks
21:42
<Bakkot>
to allow `for (;;) { (do { break;} ) }` you need to make the error not trip
21:42
<devsnek>
nothing explicitly allows `x: { break x; }`
21:42
<devsnek>
er
21:43
<devsnek>
`x: { { break x; } }`
21:43
<devsnek>
you don't need to add anything for `x: { do { break x; } }` to work there
21:43
<Bakkot>
yes, you do
21:44
<Bakkot>
you need to modify `ContainsUndefinedBreakTarget` to not error in that case
21:44
<Bakkot>
currently it would
21:44
<Bakkot>
(ok it might not, but it certainly would for e.g. `x: if(do{break x;}) ;`
21:44
<Bakkot>
)
21:44
<rbuckton>
LabelledEvaluation doesn't apply to expressions, so the labelSet wouldn't be populated.
21:44
<Bakkot>
right
21:44
<Bakkot>
so
21:44
<Bakkot>
it would error
21:44
<devsnek>
ok true labelled evaluation would need to be updated
21:45
<Bakkot>
labelled evaluation is runtime semantics
21:45
<Bakkot>
you'd also need to update the static semantics
21:45
<devsnek>
indeed
21:45
<devsnek>
are you sure about the if statement?
21:45
<rbuckton>
devsnek: a different example might be this: `switch (x) { case 0: do {break; } }` since it would have passed the `ContainsUndefinedBreakTarget` check
21:46
<rbuckton>
Or `do { do { break; } } while (true);` ;)
21:46
<devsnek>
lol
21:46
<devsnek>
got it
21:46
<Bakkot>
devsnek I am not sure if it would error. But either it would error, or `x: if(do{break y}); ` would not. so it would need to be updated one way or the eother.
21:47
<Bakkot>
you'd definitely to propagate the about labels/breaks through expressions, where currently and with my proposed semantics you do not need to do that.
21:47
<devsnek>
i'll write up the changes for that if you want
21:47
<Bakkot>
so, yeah, like I said; it's actually strictly simpler to spec my propose semantics. not that this should have much weight
21:47
<Bakkot>
nah
21:47
<Bakkot>
I don't think spec difficulty should matter, like I say
21:48
<Bakkot>
this was just a response to rbuckton's concern about the spec difficulty of my proposed semantics
21:52
<jorendorff>
devsnek: Other iterator prototypes have a toStringTag, like <https://tc39.es/ecma262/#sec-%arrayiteratorprototype%-@@tostringtag>;.
21:52
<jorendorff>
devsnek: is it intentional that %WrapForValidIteratorPrototype% does not?
21:52
<devsnek>
no
21:53
<jorendorff>
ok, i'll ask adam if he can file a PR to add it
21:55
<shu>
rbuckton: so i think i can be convinced that selective banning may be the desirable solution as a follow-on, especially if a version without control flow is shipped first
21:55
<shu>
and we get to see what the uptake is like
22:47
<jorendorff>
hmm. are do-expressions already in any of the compile-to-js languages?
22:47
<jorendorff>
curious to know what the uptake is like already
22:48
<jridgewell>
Babel?
22:48
<ljharb>
jorendorff: lots of us do a lot of strong advocacy for people to never use pre-stage-3 proposals, so it may not be that clear a picture
22:48
<leobalter>
@jorendorff jridgewell https://babeljs.io/docs/en/babel-plugin-proposal-do-expressions
22:49
<Bakkot>
babel's is broken-ish though
22:50
<Bakkot>
but still popular with jsx, I think
22:50
<jridgewell>
Yah, I think JSX expressions is the biggest usecase
22:51
<jridgewell>
[Repl](https://babeljs.io/repl#?browsers=ie%2011&build=&builtIns=false&spec=false&loose=true&code_lz=MYewdgzgLgBCMF4YBN4G8BQMYEsBmMAFFAE4CuApgJQybbamVYwC-MFANhBbc9ngEMuFZiwwsgA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=true&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=stage-1&prettier=false&targets=&version=7.10.2&externalPlugins=)