00:52
<Axel Rauschmayer (self-employed)>
Sorry, off-topic, but could we do a quick test if showing my slides works?
00:55
<Robert Pamely>
Is the video conference live?
00:56
<Robert Pamely>
I see waiting for host
00:56
<bterlson>
it is not started yet
00:56
<Axel Rauschmayer (self-employed)>
Me too. We need a host, yes.
00:56
<bterlson>
waiting for an igalian to do so :)
00:56
<Robert Pamely>
ok thanks Brian
00:56
<Axel Rauschmayer (self-employed)>
Hehe
00:59
<Ashley Claymore>
Sorry, off-topic, but could we do a quick test if showing my slides works?
very on-topic! :D top tip: sometimes have to restart the browser if only just given permission to share screen for the first time
00:59
<Axel Rauschmayer (self-employed)>
Yeah, already did that (the screen sharing background helps with testing).
01:01
<littledan>
I guess you can try screen sharing now?
01:09
<littledan>
Are we ready to get started?
01:09
<shu>
haven't we already started?
01:10
<bakkot>
we have in fact already started
01:10
<snek>
axel has been presenting for like 5 minutes
01:14
<littledan>
Oh! A problem on my end
01:15
<Michael Ficarra>
what is meant by "a wrapping API" here?
01:16
<ljharb>
isn't Iterable.from() already a wrapping API? it's just that most builtin iterators are/will be pre-wrapped
01:16
<bakkot>
something like Jquery
01:16
<bakkot>
where you do $(document.querySelectorAll(...)) and then get a new thing that has a bunch of helper functions
01:17
<Michael Ficarra>
how is that different than what we do?
01:17
<bakkot>
you don't need to wrap most of the time
01:17
<HE Shi-Jun>
A real example of "wrapping API"
01:17
<HE Shi-Jun>
Emitter proposal
01:18
<HE Shi-Jun>
https://github.com/tc39/proposal-emitter
01:18
<bakkot>
like if you do map.values().filter() there's no explicit wrapper
01:18
<ljharb>
right, builtins are "pre-wrapped"
01:18
<ljharb>
(or some better way to describe it)
01:18
<Michael Ficarra>
yeah, that's kinda my mental model
01:19
<HE Shi-Jun>
Emitter proposal also use function style.
01:19
<HE Shi-Jun>
const { on, map, filter, run } = Emitter

run(
  on(document, 'click')
, filter(ev => ev.target.tagName === 'BUTTON')
, map(ev => ({ x: ev.clientX, y: ev.clientY }))
, coords => console.log(coords)
)
01:20
<Michael Ficarra>
that's applicative style, no?
01:21
<ljharb>
Axel Rauschmayer (self-employed): re builtin modules, pending that proposal advancing, short answer is no, not in the cards (shu's queue item covers this also)
01:23
<Michael Ficarra>
it's iterable ONCE, which is the important point
01:24
<Michael Ficarra>
iterators are kind of lying by implementing Symbol.iterator
01:25
<shu>
snek: wait, you are in favor of using iterable helper functions as Axel proposed?
01:26
<Michael Ficarra>
shu: no I think they were saying iterator helpers as functions (conditional on pipe operator)
01:26
<shu>
we need a better word than "functions" here
01:26
<Michael Ficarra>
non-this-value-users
01:27
<ljharb>
"standalone functions" vs "methods" imo
01:29
<shu>
yes that's good
01:31
<ljharb>
Axel Rauschmayer (self-employed): for clarity; consensus typically means "some explicit yes's and no explicit no's" and does not imply or require universal enthusiasm :-)
01:32
<rbuckton>
I'm primarily in favor of the standalone function approach because its more flexible and is composable with third-party packages without the need for prototype patching (which is obviously bad). Yes that puts more of a dependency on pipeline, but I think pipeline can advance once the topic variable issue is addressed.
01:34
<snek>
to be clear i was concerned about wasting work on consensus, not work on spec text
01:35
<Michael Ficarra>
oh god, a superclass of all collection types would be as bad an idea as Object.prototype already is
01:36
<shu>
haha oh no please no
01:36
<snek>
class TCPConnection extends Collection
01:36
<ljharb>
we could just call it FragileBaseClass
01:36
<ljharb>
oh wait sorry wrong channel
01:36
<Michael Ficarra>
why do so many people have this same bad idea?
01:37
<rbuckton>
ecosystem can/does have chaining-style via wrapping. And given the limited number of helper methods I'm still more likely to reach for 3rd-party.
01:38
<Michael Ficarra>
rbuckton: we have plans to add a lot more
01:38
<Michael Ficarra>
remember the current proposal is what we consider "minimal"
01:39
<ljharb>
so many more
01:39
<Michael Ficarra>
okay not that many
01:39
<snek>
i closed a lot of issues/prs for more methods
01:39
<Michael Ficarra>
like a dozen?
01:40
<bakkot>
https://github.com/tc39/proposal-iterator-helpers/issues?q=is%3Aissue+is%3Aclosed+label%3A%22good+follow-on+proposal%22
01:40
<rbuckton>
But until you do, and as long as there is an iterator helper I need that isn't in that list, I'm still bouncing between methods and functions. Until we have pipeline, but if we have pipeline I'd still rather have functions.
01:42
<Michael Ficarra>
we have 15 min underflow during this session, we might want to just let this topic go over by 15 min?
01:43
<Michael Ficarra>
especially given that this presenter is an invited expert, it would be nice to be more lenient with the timebox
01:43
<Anthony Bullard>
I don't think these functions would be global, correct Axel Rauschmayer (self-employed) ?
01:43
<Anthony Bullard>
I'm assuming they would be in a global namespace, like Math
01:43
<ljharb>
what would we call it tho - "Iterable" isn't a "thing", it's a trait
01:44
<rbuckton>
I have all of these as functions (@esfx/iter-fn and @esfx/async-iter-fn), and wrapping via a Query class (@esfx/iter-query and @esfx/async-iter-query). All of these are iterable (multi-shot if source returns a new itererator each time, single shot if the source returns the same iterator each time).
01:44
<ljharb>
to be fair, iterators aren't a thing either, but the helpers proposal makes a wrapped iterator A Thing, via Iterator.from
01:44
<Anthony Bullard>
That's a great point, but is there a concern with there being a global for the trait?
01:44
<ljharb>
it's just weird
01:45
<ljharb>
because wrapping iterators makes sense; wrapping iterables i'm not sure does
01:45
<ljharb>
Iterable.from(set) wouldn't be a Set, for example
01:45
<rbuckton>
And if you do Iterator.from(x).map(), Query.from(x).map() is pretty much the same.
01:45
<Anthony Bullard>
I agree, but that is kind of the way that Rust traits get compiled down
01:46
<bakkot>
C#'s IEnumerable is reusable (I believe), but that has super weird performance implications
01:46
<Anthony Bullard>
No, it's an Iterable, like the name of the namespace - not that class or type, but a type that implements that trait
01:46
<ljharb>
JS doesn't have a type system like that tho
01:47
<Anthony Bullard>
It would be strange for functions in Iterable namespace to return a Set
01:47
<snek>
i was going to mention this on the queue but how we explained reusability in the past is via functions. for example how do you make for..of reusable, you wrap it in a function that you call multiple times.
01:47
<bakkot>
it would also be strange for them to return things that are not reusable
01:47
<Michael Ficarra>
I wish this proposal hadn't conflated using the function style with the change to iterables; using functions is a reasonable request, but operating on iterables is not
01:48
<snek>
i was going to mention this on the queue but how we explained reusability in the past is via functions. for example how do you make for..of reusable, you wrap it in a function that you call multiple times.
now the for..of is not relevant itself, you could be manually consuming an iterator or you could be using a generator or whatever, you just end up with a nice abstraction boundary of a function. this was also a big point with Number.range if anyone remembers that.
01:48
<bakkot>
you could extend iterator.prototype and have FancyIterator.from(thing).fancyMethod() etc
01:48
<bakkot>
seems fine
01:48
<ljharb>
re shu 's queue item - function filter(iterable, filterer) { return Iterator.from(iterable[Symbol.iterator]()).filter(filterer); } i think?
01:48
<Anthony Bullard>
I agree with that Michael Ficarra . I wish static methods or namespaced sets of functions are a better approach - and much better when we get pipes
01:48
<rbuckton>

I could imagine a Query.use(...fns) that returns something that mixes in a bunch of functions as methods that can then be used for chaining, i.e.:

// built-in 
Query.from(ar).map()// filter(), etc.

const MyQuery = Query.use({ groupBy, join, groupJoin }); // subclass Query, patching in functions as methods
MyQuery.from(ar).groupBy() // join(), etc.
01:49
<bakkot>
but also, the language has had built-in Array.prototype.map forever while underscore had _.groupBy or whatever, and that was fine; the ecosystem things don't necessarily need to look like built-in things
01:49
<bakkot>
(to shu's point)
01:51
<bakkot>
also the language will always have Array.prototype.map, so it's not like we can avoid having method-based things in the stdlib at this point
01:51
<rbuckton>
The .use concept could work with Iterator, though (i.e., subclass Iterator, mix in and wrap the provided methods).
01:51
<shu>
i think as a way of choosing defaults for the standard library, i see no compelling reason aside from taste to deviate from what we have been doing since the language's inception with prototype methods
01:51
<shu>
the functional style is easily polyfilled
01:51
<shu>
let those adherents import a library, that seems sufficient?
01:53
<ljharb>
if/after pipeline has landed, i think there will be compelling reasons. but until then, i agree that there isn't. and i don't think proposals should wait for that.
01:53
<bakkot>
s/after/if/
01:53
<ljharb>
yes thanks, edited
01:53
<rbuckton>
let those adherents import a library, that seems sufficient?
My concern is having to mix functions from a 3rd party with methods on Iterator.prototype, makes for hard to read code.
01:53
<ljharb>
it wouldn't be hard to read with pipeline tho :-)
01:53
<Michael Ficarra>
ljharb: just like we shouldn't have to wait for a way to list all intrinsics, right? 😉
01:53
<shu>
rbuckton: that seems unavoidable
01:54
<shu>
JS is not a functional style language
01:54
<shu>
it has some combinators here and there
01:54
<rbuckton>
if/after pipeline has landed, i think there will be compelling reasons. but until then, i agree that there isn't. and i don't think proposals should wait for that.
Is there anything pipeline is waiting on aside from picking the topic?
01:54
<ljharb>
yep! i'm on your side for that one, altho ofc we still need that "way"
01:54
<Michael Ficarra>
ljharb: I hope to hear your support for that later then 🙂
01:55
<bakkot>
if you want to use more things in a method-based style, you can write a thing extending Iterator.prototype and put more methods on it
01:55
<bakkot>
that works fine
01:55
<bakkot>
Iterator has no slots
01:55
<bakkot>
and will never have slots
01:55
<ljharb>
even if it did, extending Iterator would give you them
01:56
<bakkot>
Bradford Smith: re your queue topic, you don't have to implement a bunch of stuff, you just __proto__: Iterator.prototype
01:57
<bakkot>
to be clear, I am very, very opposed to function-based style even in a world in which we have pipeline
01:57
<bakkot>
I do not think pipeline meaningfully changes this conversation
01:58
<HE Shi-Jun>
to be clear, I am very, very opposed to function-based style even in a world in which we have pipeline
Is there any special reason ?
01:58
<bakkot>
Array.prototype.map already exists, and will always exist
01:58
<bakkot>
mapping over iterators should work like mapping over arrays
01:59
<bakkot>
not with completely different style and completely different syntax
01:59
<shu>
the "consistency" arguments presented so far are very myopic IMO
01:59
<Jack Works>
if you want to use more things in a method-based style, you can write a thing extending Iterator.prototype and put more methods on it
and then we need multiple inheritance to mixing them together Library1Iterator.prototype and Library2Iterator.prototype
01:59
<shu>
ISTM to boil down to "my code is already functional style, it'd be nice if i didn't need a 3p library to keep that style"
01:59
<shu>
i daresay that's a minority?
02:01
<Jack Works>
you must see this https://github.com/fantasyland/fantasy-land 😂
02:01
<ljharb>
both clauses of that are a minority
02:01
<ljharb>
people who avoid third party libs, and codebases that are predominantly functional
02:01
<bakkot>
you must see this https://github.com/fantasyland/fantasy-land 😂
the current iterator helpers champion is a contributor to that
02:02
<bakkot>
Michael Ficarra in particular
02:05
<rickbutton>
if not pipeline, the :: call syntax would also alleviate some of this burden of swapping styles
02:05
<rickbutton>
don't remember what the feeling on this at the time was tho
02:06
<waldemar>
A bigger problem than style is semantics. See the problem that Kevin and I raised.
02:11
<HE Shi-Jun>
If talking about semantics , I also have the concern, should we extend Iterator too much? IMO, iterator should be simple and only use as underlying mechanism, why not use a separate concept for data transformation? Like Java Stream, or Emitter proposal?
02:13
<bakkot>
java streams would have been on iterator if they could have
02:13
<bakkot>
but the existing iterator interface, in Java, has .remove and stuff
02:13
<bakkot>
and has distinct hasNext and next methods
02:13
<bakkot>
which are awkward with helpers
02:13
<bakkot>
those facts are the only reason Stream exists
02:14
<bakkot>
I can try to track down the mailing list discussions from when Stream was introduced
02:14
<bakkot>
but we don't have those problems, so we don't need to introduce a new thing
02:14
<bakkot>
which is nice
02:16
<HE Shi-Jun>
But we have other problems like Iterator interface. There are confusions on what Iterator means in the ecosystem. For example, Iterator helpers actually require TS to change the definition of Iterator.
02:17
<bakkot>
That seems like an extremely minor problem, given that we're designing a language which will be in use for decades
02:17
<HE Shi-Jun>
I don't think it's a "extremely minor problem".
02:17
<bakkot>
TS will rename Iterator to IteratorLike
02:17
<bakkot>
it will be fine
02:19
<Jack Works>
it will be a ecosystem breaking change
02:19
<HE Shi-Jun>
Yeah, TS always have the way to do incompatible change, but obviously it have cost ,not only TS itself, but also the whole ecosystem
02:19
<ljharb>
sure. but that's kind of an unavoidable cost when building on top of a standard, outside that standard, no?
02:19
<bakkot>
I suspect there are relatively few things which use the Iterator type, and it is a very easy migration to do
02:20
<Jack Works>
use Iterator as IteratorLike, and ABikeSheddingNameIterator as Iterator is good IMO
02:20
<bakkot>
relative to the design of the language for the next several decades, the cost of that particular breaking change is small
02:20
<HE Shi-Jun>
Again, it's not only TS problem, we also change the Iterator in the spec from a Interface(protocol) to concrete class (prototype).
02:20
<ljharb>
in the spec it'd be both. it's already both, it's just that the concrete class isn't really exposed to users, and this proposal would expose it.
02:20
<bakkot>
speaking as editor of the specification, the name of the interface in the spec is basically the lowest possible priority
02:21
<Jack Works>
relative to the design of the language for the next several decades, the cost of that particular breaking change is small
(ESM & CJS co-op: 👀)
02:21
<bakkot>
Jack Works
02:21
<bakkot>
that particular breaking change was much more serious
02:21
<rbuckton>
I suspect there are relatively few things which use the Iterator type, and it is a very easy migration to do
In TypeScript? Actually there are a fair amount of folks using Iterator directly, changing that would be breaking, but the interface Iterator doesn't have to align with the value Iterator.
02:21
<HE Shi-Jun>
speaking as editor of the specification, the name of the interface in the spec is basically the lowest possible priority
I don't mean the cost of spec editors, but the cost of changing concept which js programmers/educators already have.
02:23
<rbuckton>
In TypeScript? Actually there are a fair amount of folks using Iterator directly, changing that would be breaking, but the interface Iterator doesn't have to align with the value Iterator.
Which is also why I've been fairly confident in saying "not every Iterator has a [Symbol.iterator] method" and "not every Iterator inherits from %IteratorPrototype%", because it's come up often enough over the last few years.
02:24
<ljharb>
sure, but that's what Iterator.from is for - and iterator helpers would push all the authors of those iterator-likes to in fact make them have both of those things
02:24
<bakkot>
I have myself written iterators which don't inherit from Iterator.prototype, but writing iterators manually is a pretty unusual thing to do, and having to add __proto__: Iterator.prototype to such things in the future is not such a large cost, I think.
02:27
<HE Shi-Jun>
I guess "{proto: Iterator.prototype}" doesn't work in some runtime (deno?)
02:27
<bakkot>
it does
02:27
<bakkot>
deno deletes the Object.prototype accessors
02:27
<bakkot>
not the syntax
02:27
<bakkot>
it's a required part of the spec
02:27
<Jack Works>
syntax works everywhere
02:27
<rbuckton>
ljharb: re: your comment in the queue. With the exception of yield* "abc", for(const x of "abc"), and ..."abc (i.e., very explicit actions on a supplied iterable), I really do think any new API that accepts an Iterable should restrict it to Object iterables.
02:29
<rbuckton>
Pretty much every other use case where you end up spreading a string is probably a bug (except Array.from). I'd argue that if you wrote new Set(value) and value was a string, its most likely a bug. If a new API accepted an iterable argument, I'd push hard for requiring you to do [..."abc"] if you really wanted to pass in code points.
02:31
<rbuckton>
forEach shouldn't be in the middle of a chain
02:31
<rbuckton>
that would be something like .tap.
02:32
<bakkot>
for tap, see this thread, particularly my last comment: https://github.com/tc39/proposal-iterator-helpers/issues/13#issuecomment-1210164187
02:32
<msaboff>
Justin Ridgewell: what is your abbreviation?
02:32
<Justin Ridgewell>
The undefined return value is my my hated part of Array.p.forEach.
02:32
<Justin Ridgewell>
JRL
02:33
<bakkot>
https://github.com/tc39/notes/blob/6f7e075341e435f22777b07a3ee5141442d2d8a7/delegates.txt#L231
02:35
<rbuckton>
I disagree, I feel indexed() is over complicated, and passing in a counter is much easier to reason over and better for refactoring. The fact that we pass a counter and not the source as a 3rd arg like we do for Array is indicative enough that its not an index.
02:36
<ljharb>
erights: so i'm looking, and now i can't find the file i remember looking at - certainly you'll have https://github.com/ljharb/get-intrinsic/blob/main/index.js, but in test262 it's all single lines of code in individual test files, like https://github.com/tc39/test262/blob/6e61dd7754e7c94ebcf3ee679cb8db3c54a37b50/test/built-ins/ThrowTypeError/length.js#L16-L19 - which isn't a single location, but at least means there's a canonical way to "get at" the intrinsic
02:36
<ljharb>
we don't provide the source on array reduce/reduceRight, either, and that argument is rarely used anyways, so i don't think that indicates anything
02:37
<rbuckton>
I've taken to think of the "iterator helpers" as "one shot iterable helpers that happen to be on Iterator.prototype and can be accessed by any iterable using Iterator.from()"
02:37
<ljharb>
i agree with that mental model, but i don't think that speaks for or against "counter"?
02:38
<rbuckton>
i agree with that mental model, but i don't think that speaks for or against "counter"?
Sorry, that comment wasn't related to the "counter" discussion.
02:40
<bakkot>
rbuckton: I expect to do a fair amount of document.querySelectorAll(...).values().map().find() etc
02:40
<rbuckton>
There's a difference in intention. .reduce is an aggregation operation producing a scalar value. It's perfectly reasonable to expect .map and .filter to care about a counter. .map with a counter can be used to map into even/odd rows. .filter with a counter could reasonably be used to skip every other value. Those cases exist with Array .map and .filter today, and being able to refactor to iterator helpers seems like a good thing.
02:40
<ljharb>
re strings, i guess we could have an AO like IsContainer or something, that returns true for Object, and eventually Record and Tuple, and require that in the helpers - and then Strings would never be iterated by default
02:42
<Justin Ridgewell>
Are tuples concat spreadable?
02:42
<Justin Ridgewell>
Apparently.
02:45
<rickbutton>
to confirm, whats the problem with iterable strings? that they are iterable at all, or that they don't iterate over the expected contents?
02:45
<HE Shi-Jun>
to confirm, whats the problem with iterable strings? that they are iterable at all, or that they don't iterate over the expected contents?
tab wrote a article explained that
02:45
<rickbutton>
ooh
02:46
<bakkot>
https://www.xanthir.com/b4wJ1
02:46
<rbuckton>
to confirm, whats the problem with iterable strings? that they are iterable at all, or that they don't iterate over the expected contents?

Its bad for refactoring, and doesn't match user expectations.

["abc"].flatMap(x => x); // ["abc"]
["abc"].values().flatMap(x => x).toArray(); // ["a", "b", "c"] if we don't limit to objects
02:46
<rickbutton>
ah I see
02:46
<ljharb>
(iow we should have done String.prototype.codeUnits() and String.prototype.codePoints() and not had String.prototype[Symbol.iterator] at all)
02:47
<rickbutton>
^ was just going to saythat
02:47
<rickbutton>
but alas
02:47
<HE Shi-Jun>
(iow we should have done String.prototype.codeUnits() and String.prototype.codePoints() and not had String.prototype[Symbol.iterator] at all)
could we add codeUnits and codePoints now?
02:47
<ljharb>
absolutely, we just need a proposal and consensus (so, easy, right?) we wouldn't ever be able to unbreak strings tho :-(
02:48
<rbuckton>
How about .graphemes()?
02:48
<ljharb>
yes please, altho then you'll be pointed to Intl.Segmenter
02:48
<HE Shi-Jun>
How about .graphemes()?
I guess graphemes are locale related
02:48
<rickbutton>
delete String.prototype[Symbol.iterator] ez
02:49
<Richard Gibson>
and for good reason—grapheme cluster segmentation is locale-sensitive
02:50
<HE Shi-Jun>
Swift use locale-independent grapheme cluster (I don't remember the correct term), but may have some issues (I don't fully know).
02:50
<ljharb>
i'm mad at unicode, or maybe just all human beings, for making graphemes differ based on locale
02:51
<jschoi>
absolutely, we just need a proposal and consensus (so, easy, right?) we wouldn't ever be able to unbreak strings tho :-(
Serious question: Would a .codePoints proposal really get much traction, or would it get too much pushback that We Already Have the Default String Iterator?
02:51
<HE Shi-Jun>
Just like JS have compatible requirements, unicode also, so ....
02:51
<ljharb>
[Symbol.iterator]() is utterly unergonomic tho
02:51
<HE Shi-Jun>
Array.values() vs Array[Symbol.iterator] 😅
02:54
<rbuckton>
I don't think you can safely interleave next() and return() because of finally since that would put your source in a very weird state (pre-emptying the current await that might be in a try..catch..finally, etc.)
02:55
<bakkot>
with an actual generator that's definitely true
02:55
<bakkot>
but generators have an internal queue of those calls, so no problem there
02:55
<Anthony Bullard>
Michael Ficarra: Could you craft a real-life code example of a usecase for interleave next/return
02:55
<Anthony Bullard>
?
02:56
<jschoi>
Array.values() vs Array[Symbol.iterator] 😅
Nice. I figure that the .codePoints() proposal would be bundled with code-unit iterator(s?) and make the point that “we should encourage developers to use for (p of str.codePoints()) rather than for (p of str) as much as possible”.
02:56
<bakkot>
we should not encourage developers to do that
02:56
<bakkot>
for (p of str) is fine
02:56
<bakkot>
no objections to having a codePoints helper though
02:57
<Michael Ficarra>
msaboff: I just keep delegates.txt open in another tab when I am taking notes
02:57
<nicolo-ribaudo>
We should all put our abbreviation in the jitsi display name
02:57
<jschoi>
for (p of str) is fine
I do suppose it comes down to how much one agrees with https://www.xanthir.com/b4wJ1
02:57
<HE Shi-Jun>
for (p of str) is fine
It's not clear what p is.
02:57
<bakkot>
jschoi: I agree with that thing but that ship has sailed
02:58
<bakkot>
strings are iterable, we can't take that back
02:58
<Ashley Claymore>
Symbol.iteratorV2 but don't put it on string.prototype (sorry tdz post)
02:58
<rbuckton>
I'd rather see for (p of str.codePoints()) because its more intentional. I've never been a fan of the disparity between str[i] and str[Symbol.iterator]().
02:59
<jschoi>
The default string iterator can’t be made illegal, but developer guidance about it can change, right? Not that I feel that strongly one way or the other about what we should do about the situation myself…
02:59
<HE Shi-Jun>
strings are iterable, we can't take that back
yeah we can't, but at least linter could warn that if we give people other better options.
02:59
<bakkot>
I don't think developer guidance helps with the actual problems in that essay
02:59
<jschoi>
Fair enough.
03:00
<bakkot>
I guess it helps with the "no correct way to iterate a string" thing
03:00
<bakkot>
but not the "infinite descent" thing, or the "accidentally passing it to something like the Set constructor" thing
03:00
<HE Shi-Jun>
TS (or other type checker) can warn that (theoretically)
03:01
<bakkot>
it can already warn about passing a string where an iterable is expected, though
03:01
<bakkot>
can and possibly should
03:01
<bakkot>
don't need new developer guidance for that
03:02
<bakkot>
(maybe a job for tslint rather than TS proper)
03:02
<jschoi>
it can already warn about passing a string where an iterable is expected, though
In that case, being explicit with .codePoints would be nice for the compiler as well as human readers, right? That’s kind of a case where developers “should” use .codePoints instead of the default iterator.
03:02
<rbuckton>
Unfortunately, TS doesn't really have "warnings", per se. Every diagnostic has the same level.
03:03
<bakkot>
every diagnostic is a warning, that's what // ts-expect-error is for :P
03:03
<bakkot>
jschoi: yeah that's fair
03:03
<Ashley Claymore>
We should all put our abbreviation in the jitsi display name
+1 (and Jitsi should make it even clearer who is currently talking even if someone else is screen sharing)
03:03
<rbuckton>
I'd much rather pass a str.codePoints() into something that expects an iterable when I know I want the code points, vs [...str] (both because the former is clearer and the latter is eager)
03:04
<jschoi>
…Though come to think of it, we probably should call it something like .byCodePoints() or .codePointStrings() or something. Because the language already uses “code points” to refer to integers: String.codePointAt returns integers.
03:04
<Anthony Bullard>
+1 (and Jitsi should make it even clearer who is currently talking even if someone else is screen sharing)
Ashley Claymore: 1000% this
03:04
<rbuckton>
(and yes, you could do str[Symbol.iterator]() to not be eager).
03:04
<Anthony Bullard>
I now put jitsi in full screen in tile mode on my left monitor, and the etherpad on the right monitor
03:05
<bakkot>
…Though come to think of it, we probably should call it something like .byCodePoints() or .codePointStrings() or something. Because the language already uses “code points” to refer to integers: String.codePointAt returns integers.
ugh, yeah
03:08
<Anthony Bullard>
Is it possible for us to have some sort of coordination during note taking, or has something like that been attempted? Three people live editing the transcription gets very frustrating
03:10
<Anthony Bullard>
And does the transcription bot just get a single stream of audio, or would it have a way of detecting the speaker and including those annotations?
03:10
<bakkot>
just a single stream of audio
03:10
<rbuckton>
Kinda wish we had a char-like concept in JS (at least, the C# version that is always a wide char) that wasn't just Number/String
03:11
<Anthony Bullard>
Too bad we ran out of quotes to use for it
03:11
<bakkot>
it is in principle possible to write something which talks to the Jitsi API to detect the current speaker but that would be a lot of work
03:11
<bakkot>
PRs welcome though https://github.com/bakkot/transcribe-to-gdocs
03:11
<Michael Ficarra>
I think the latest version of Jitsi already has this though, right?
03:12
<bakkot>
has what?
03:12
<bakkot>
has live transcriptions output to google docs? no it does not
03:12
<Michael Ficarra>
not to gdocs, to some sort of log, I can look for the PR later
03:12
<HE Shi-Jun>
Kinda wish we had a char-like concept in JS (at least, the C# version that is always a wide char) that wasn't just Number/String
Note sure we have good use case of char?
03:13
<Anthony Bullard>
Note sure we have good use case of char?
Comparing characters in a way that does involve looking up charcodes?
03:15
<jschoi>
It’d have been better for everyone if it was never named “char” in Java but rather “utf16unit”. :’)
03:16
<Anthony Bullard>
Yeah, char has connotations of ASCII, or at least 8-bit character
03:17
<Anthony Bullard>
But maybe not to your workaday JS developer
03:19
<jschoi>
It’s my opinion that, because “character” has so many different meanings (8/16/32-bit code units, code points, combining character clusters, grapheme clusters), it’s too ambiguous and should generally be banned from technical documentation and APIs and replaced by more specific phrases. But that’s me……
03:19
<jschoi>
The word is a real source of confusion though; there’s a reason why it takes up basically a whole section of the Unicode FAQ.
03:19
<Anthony Bullard>
At this point in time, that's probably correct
03:20
<bakkot>
"character" in the JS spec, used in the regex processing part, means either code point or code unit depending on whether the current regex is /u or not
03:21
<bakkot>
that's a fun one
03:24
<Anthony Bullard>
oof
03:25
<Anthony Bullard>
It seems like Strings, when looked from the modern landscape are at least as complex as time.
03:25
<bakkot>
mmmmmmm no time seems harder still
03:25
<Anthony Bullard>
In terms of representation, manipulation, and inspection
03:26
<Anthony Bullard>
I probably need to sit down and write that thought out to sanity check myself
03:28
<Anthony Bullard>
I'm sure the Temporal champions would very quickly disabuse me of that proposition
03:28
<jschoi>
Strings are hard if only because text is hard, and text is hard because human writing systems are nuts.
Then again, time is nuts too, so.
03:29
<Anthony Bullard>
There are a lot of similar problems there actually
03:29
<Anthony Bullard>
For much of the same reasons
03:29
<rbuckton>
At least strings in JS support operators. Temporal, unfortunately, does not :/
03:30
<HE Shi-Jun>
It’s my opinion that, because “character” has so many different meanings (8/16/32-bit code units, code points, combining character clusters, grapheme clusters), it’s too ambiguous and should generally be banned from technical documentation and APIs and replaced by more specific phrases. But that’s me……
maybe we could use "rune" (rust, go use that term?)
03:30
<bakkot>
strings probably shouldn't've supported operators
03:30
<bakkot>
lexicographic ordering is locale-dependent
03:30
<bakkot>
concatenation is crazy with combining characters
03:31
<bakkot>
=== is crazy with canonicalization and normalization
03:31
<Anthony Bullard>
maybe we could use "rune" (rust, go use that term?)
I almost forgot about runes in rust
03:31
<HE Shi-Jun>
strings probably shouldn't've supported operators
agree, but many usage of strings in the languages actually are used for symbol/keys, not for text. Though we have another "symbol" :)
03:31
<Kris Kowal>
A rune by any other name would yet be a number.
03:32
<Kris Kowal>
I hesitate to mention that Unicode does have more quote characters.
03:32
<bakkot>
aw yeah, Left-Pointing Double Angle Quotation Mark
03:33
<Anthony Bullard>
I hesitate to mention that Unicode does have more quote characters.
I made this point above. There are languages (Erlang I think) that don't use an enclosure for chars
03:33
<Kris Kowal>
There was a lovely hack for "generics" in Go that employed a source-to-source transform and aboriginal brackets.
03:35
<Anthony Bullard>
I was wrong, Elixir uses the pattern ?<character literal> to get the code point
03:35
<jschoi>
There’s a fundamental, philosophical question here: When two types have an equivalence relation, when should they be unified? In this case, should code units be unified or separated from integers? But it’s a far more general problem than that.
03:35
<Kris Kowal>
(My opinion is that number is a fine representation for char/rune in a language with a unified number type. It’s consistent with the rustic aesthetic.)
03:35
<Anthony Bullard>
Which might solve some usecases for the desire for characters, but not enough
03:36
<Anthony Bullard>
I think what people want is to type something like ?😀 and get the code point(s)
03:37
<Anthony Bullard>
But there is probably a lot wrong with that idea
03:37
<Anthony Bullard>
I probably should stop prognosticating on such matters at this hour
03:38
<Kris Kowal>
I can tell you what I want is to be able to query the kernel terminal discipline for how many columns a string is going to render into in the connected tty without having to pre-render them all, but I also know I’m not going to get that ever.
03:39
<Kris Kowal>
Some would call my motivating use case esoteric: emoji + tty + roguelike
03:41
<Kris Kowal>
But as bakkot mentioned, string concatenation only hints at the problem. If a streaming an emoji with combining characters is interrupted by a write flush, the tty is compelled to render the incomplete sequence, followed by the remaining incomplete sequence, and the outcome is not consistent.
03:41
<jschoi>
…Have any text-based roguelikes attempted to use all of (printable) Unicode for its symbols, using a pan-Unicode bitmap font like GNU Unifont? But wrong channel, I guess.
03:41
<Anthony Bullard>
That is why emoji are largely not fit for tty
03:42
<Kris Kowal>
Yes, and on the web, you’re not going to know enough about your string until you run it by font metrics.
03:42
<Anthony Bullard>
But much more essential characters face the same problems I'm sure (CJK, Devanagari?)
03:43
<Kris Kowal>
Hangul, for certain.
03:43
<Kris Kowal>
And of course the hypothetical code page of combining tengwar and tehtar.
03:43
<Anthony Bullard>
I never used Hangul in a tty scenario
03:43
<jschoi>
Emoji display is different than emoji characters; you don’t necessarily need combining characters or variation sequences just to have the characters themselves printed on a streaming TTY, as long as the TTY supports SMP characters.
03:44
<jschoi>
I…think…
03:44
<Kris Kowal>
Hangul evidently have both combining and non-combining glyphs depending on when they entered unicode.
03:44
<Anthony Bullard>
That is surprising, Hangul is a very simple, small script - I wonder how they would have entered unicode at different times?
03:44
<jschoi>
As far as I know, modern Hangul entered Unicode all at once, both composed and decomposed.
03:44
<Anthony Bullard>
Maybe historical glyphs?
03:45
<jschoi>
Otherwise, they wouldn’t’ve been able to create the special character-name rules for the composed characters.
03:45
<Anthony Bullard>
There are I think 3 historical glyphs that are obsolete
03:45
<Anthony Bullard>
I haven't spoken or written Korean in any meaningful respect in 17 years, so that's probably wrong
03:47
<jschoi>
…Yeah, the Hangul Syllables block was entirely added in Unicode 2.0 / 1996. Though it’s all modern of course.
03:47
<rkirsling>
then again some syllables could be viewed as hypothetical
03:47
<Anthony Bullard>
then again some syllables could be viewed as hypothetical
No obsolete glyphs in unicode, but we have Linear B?
03:51
<jschoi>
For what it’s worth, as far as I know, every syllable combination encoded in Hangul Syllables is in actual use. I do not have data to back this up.
03:51
<Anthony Bullard>
7 obsolete Hangul letters, 5 simple characters, 2 obsolete ssang(double) characters. Would love to hear what ssang-hieut sounded like...
03:53
<Anthony Bullard>
then again some syllables could be viewed as hypothetical
A lot of the bizarre ones are used for onomatopoeia
03:55
<Anthony Bullard>
And of course the hypothetical code page of combining tengwar and tehtar.
Hopefully not on the same screen as emoji...
03:56
<Kris Kowal>
Hopefully not on the same screen as emoji...
🧝‍♀️?
03:56
<jschoi>

Code blocks (and code-point order) were never meant to be meaningful for users; they’re artifacts of encoding history and optimization.

This is what Unicode says, but I think Unicode could do a better job of showing this. Maybe by presenting human-user-friendly pages of writing-system repertoires…

03:57
<rkirsling>
I mean, the ones that exist need to exist by virtue of being valid combinations, but
03:57
<Kris Kowal>

Code blocks (and code-point order) were never meant to be meaningful for users; they’re artifacts of encoding history and optimization.

This is what Unicode says, but I think Unicode could do a better job of showing this. Maybe by presenting human-user-friendly pages of writing-system repertoires…

By running all the codepoints through AES, like map keys in Go.
03:58
<ryzokuken>
can folks hear me?
03:58
<bakkot>
ryzokuken if you just said "jschoi would you mind sharing your screen", yes
03:58
<bakkot>
otherwise no
03:58
<ryzokuken>
ah, yes
03:58
<ryzokuken>
I did 🙈
03:58
<rkirsling>
kind of unclear whether these would all see use: 훪 훫 훬 훭 훮 훯 ...is why I said hypothetical
03:59
<rkirsling>
if it were just combining parts, then those would be possible but you wouldn't necessarily dwell on 'em
04:00
<jschoi>
I’m sorry, give me a minute. Technical difficulties.
04:02
<bakkot>
Michael Ficarra: do you want to put conclusions from previous presentation in the notes?
04:03
<jschoi>
Can anyone hear me?
04:04
<jschoi>
(I’m a little confused on whether I’m supposed to go up right now. I can’t hear anyone right now.)
04:04
<ryzokuken>
yes
04:04
<ryzokuken>
we're waiting for you
04:04
<ryzokuken>
did you try clearing browser cache?
04:05
<bakkot>
there's been some people speaking so if you can't hear it's on your end
04:05
<bakkot>
jitsi reset my audio out/in devices, which might be the issue?
04:05
<bakkot>
had to manually change it to the right one
04:06
<ljharb>
my ios app still has no audio (and apparently nobody could hear me speak either) so i can only get it to work on the web
04:06
<Kris Kowal>
you’re on!
04:06
<Kris Kowal>
i was also unable to get audio on ios
04:20
<ljharb>

nicolo-ribaudo: your audio is harshly loud, btw, not sure if that's something you can adjust

update: it's good now!

04:29
<HE Shi-Jun>
what last question (capture) means? I suppose it should work like Array.from which have the third argument to provide this?
04:37
<HE Shi-Jun>
oh, i c. it has been fixed minutes ago :)
04:40
<HE Shi-Jun>
has is ambiguous ( hasKey / hasValue ) 😂
04:40
<Kris Kowal>
This is where we have Bradley’s conversation about covariant and contravariant sets.
04:41
<Kris Kowal>
Set.prototype.hasKey ~ CoSet.prototype.hasValue
04:42
<rbuckton>
Would the MVP for this be to only allow union/intersection with a Set (i.e., via brand check)?
04:43
<Michael Ficarra>
rbuckton: no, because the interface we use is observable and can't change in the future
04:44
<rbuckton>
I'm not clear on why this can't change? Or is it because Set is subclassable?
04:44
<Michael Ficarra>
you could either subclass Set or add Set.prototype properties to observe the API we're consuming (or lack of it)
04:45
<Michael Ficarra>
it would force our hand to use new symbols in the future I guess
04:45
<rbuckton>
The point of throwing an error for anything other than a branded Set would be to allow us to loosen that restriction in the future.
04:47
<Kris Kowal>
map.keySet(), map.valueSet() façades?
04:47
<Michael Ficarra>
rbuckton: no, that still doesn't work
04:48
<Michael Ficarra>
a set subclass could be passed today with an overridden has that side effects, which wouldn't be called if you touched the argument's slots instead of using the public API
04:48
<Michael Ficarra>
it would then break (start side effecting) if we began using the string-based API of the argument
04:48
<Michael Ficarra>
this design would force us to either continue touching internal slots (bad) or use a Symbol-based API
04:49
<ptomato>
I agree with Kevin that a good design principle is that wrong things should be obviously wrong, if possible
04:49
<ljharb>
hm, i think my queue item got skipped
04:49
<Michael Ficarra>
ljharb: I don't think so, I see it
04:49
<ljharb>
oh weird, i don't. i'll refresh
04:49
<ryzokuken>
ljharb: was there another one?
04:50
<ljharb>
nah ok, it's there, tcq just glitched i guess (i just deleted it, so now it's supposed to be gone)
04:50
<ryzokuken>
its glitching for me too, so I thought I skipped it on accident 😓
04:50
<Michael Ficarra>
consistency is hard
04:51
<ryzokuken>
now I don't see it either
04:51
<ryzokuken>
ljharb: can you add it again? I'll move it up
04:51
<ljharb>
i mean i deleted it on purpose :-)
04:51
<ryzokuken>
ah
04:52
<ryzokuken>
alright, I misunderstood
04:52
<Kris Kowal>
Petting a cat as if it were a dog works sometimes.
05:02
<rbuckton>

We could also have something like this:

Set.prototype[Symbol.asSet] = function() { return this; }

Where [Symbol.asSet] is expected to return { [Symbol.iterator](), get size(), has(value) }
Instead of two set-protocol-specific symbols, you have one, which on a set or set subtype would just return this.

05:04
<Kris Kowal>
Aye, and Map.prototype.keySet and Map.prototype.valueSet that provide façades with varying has behavior.
05:04
<Kris Kowal>
Well, valueSet oddly not valuable.
05:05
<Kris Kowal>
Sec
05:05
<rbuckton>
Aye, and Map.prototype.keySet and Map.prototype.valueSet that provide façades with varying has behavior.
Or just new Set(map.keys()), and new Set(map.values())
05:06
<Kris Kowal>
I see you’re implying Map.prototype[Symbol.asSet] that produces a façade that behaves consistently with the Set protocol. That’s reasonable.
05:06
<Kris Kowal>
new Set(map.keys()) is comparably expensive.
05:07
<Michael Ficarra>
rbuckton: yes that is also a reasonable option
05:08
<Jack Works>
is it possible to, make only two native, unmodified sets to read internal slots (so they're in the fast path)
05:08
<Jack Works>
and all other cases go in the slow but predictable path
05:09
<Michael Ficarra>
some day!
05:11
<HE Shi-Jun>
oh weird, i don't. i'll refresh
I also see some weird things happen on the queue before this topic start, and I refreshed the page. 😅
05:12
<snek>
in elixir you can do some_set |> MapSet.union(%MapSet{map: your_map})
05:13
<HE Shi-Jun>
off-topic, I hope the queue could have emoji like 👍️ on each item, so I can just show my support without add another +1.
05:14
<Michael Ficarra>
I feel like we are struggling to defend indefensible positions at this point. Who would actually want an array passed to set union/intersection to operate on its indices?
05:15
<ryzokuken>
off-topic, I hope the queue could have emoji like 👍️ on each item, so I can just show my support without add another +1.
Thanks, that's nice feedback indeed.
05:15
<rbuckton>
I feel like we are struggling to defend indefensible positions at this point. Who would actually want an array passed to set union/intersection to operate on its indices?
If you wanted that, you could just use array.keys().
05:17
<Michael Ficarra>
unfortunately it appears we do not yet have a shared goal here, which is making it impossible to debate solutions
05:19
<Michael Ficarra>
well put, ptomato
05:20
<HE Shi-Jun>
Justin Ridgewell: not only keys/values, might also entries 😅
05:21
<HE Shi-Jun>
I believe TS doesn't solve IndexedSet issue?
05:24
<rbuckton>
Or do the slow thing and have .intersection do new Set(other) and always operate on sets. :/
05:24
<Justin Ridgewell>
Have union check for size?
05:25
<snek>
hot take: don't sort NaN
05:26
<Kris Kowal>
see also: don’t pet cats
05:26
<Kris Kowal>
see also: don’t use maps as sets
05:28
<Kris Kowal>
(Ron: I see you’re not in the queue for asSet. I’d like to hear that argument.)
05:28
<Kris Kowal>
(Alas, would have liked to.)
05:29
<Michael Ficarra>
uuhh I do not recall intending to have Set/Map APIs overlap so they're interoperable
05:30
<Michael Ficarra>
can anyone definitively refute that?
05:31
<rbuckton>
I don't recall that being an intent, but do recall having a consistent API was intentional.
05:31
<Michael Ficarra>
apparently Waldemar recalls such an intent
05:32
<ljharb>
and has argued as such with https://github.com/tc39/proposal-collection-normalization
05:32
<ljharb>
(imo related to the conflicting but dually true mental models of Sets only having keys, vs only having values)
05:34
<Michael Ficarra>
lmao thenables is a perfect example of getting this design wrong
05:35
<Michael Ficarra>
I don't understand how we can be so far apart on this right now
05:39
<shu>
i think if there were more affordances for symbol-based names, we'd be back at square one
05:39
<Bradford Smith>
rbuckton: +1 to your suggestion of obj[Symbol.asSet]() return an object implementing whatever we decide to define the API of "set" to be
05:40
<Bradford Smith>
I don't love 'keys()` as the API name of the "iterate over the contents of a set" method. This discussion is an example of why it's not great.
05:40
<Michael Ficarra>
Bradford Smith: the downside of something like that is that it's a bit broad; you can't rely on finer-grained subsets of capabilties
05:40
<Michael Ficarra>
like something could have some properties of a set and not others
05:41
<Michael Ficarra>
but we're forcing ourselves to group them all together with that kind of design
05:41
<snek>
i think subsets of random classes is like
05:41
<snek>
way too big of a problem
05:41
<snek>
i like asSet
05:41
<shu>
i think i am also not a fan of having a public string-based API and a Symbol-based API where there's overlap in the semantics
05:43
<Michael Ficarra>
shu: Array.prototype.values?
05:43
<shu>
Michael Ficarra: i don't follow
05:44
<snek>
values duplicates [Symbol.iterator] on array
05:44
<Michael Ficarra>
shu: there's a bunch of string-named methods that are equivalent to a Symbol-named one (in this case Symbol.iterator)
05:44
<snek>
but i think that is OK
05:44
<shu>
that's complete overlap
05:44
<shu>
that seems fine to me
05:44
<Bradford Smith>
shu: I don't interpret rbuckton's suggestion as having a Symbol-based API. It could just as easily be that we decide that Set.prototype.intersection requires its argument to have an asSet() method, and that method must return an object that is iterable and has has() and size.
05:44
<waldemar>
NaN is not the only value for which the "return a-b" sort comparator is inconsistent.
05:44
<Michael Ficarra>
shu: are we talking about partial overlap?
05:44
<shu>
Bradford Smith: i wasn't responding to rbuckton's but to kevin's suggestion of @@SetHas and @@SetSize
05:45
<snek>
i am now wondering how long until this proposal morphs into the first class protocols proposal
05:47
<shu>
Michael Ficarra: yeah the partial overlap is where a lot of my dislike comes from. concretely, today, there's the public string-based API for Maps that's, like, Set-like enough because we don't have additional algorithmic constraints stipulated by union and intersect. kevin's proposal for the symbol API is now like, "actually, even more set-like, in a different namespace, with this small delta in guarantees"
05:47
<rbuckton>
Symbol.queryInterface when?
05:47
<Michael Ficarra>
shu: ah gotcha
05:48
<shu>
that's what i meant originally by "ad hoc protocol"
05:48
<shu>
or at least, the ad hoc-ness
05:49
<Michael Ficarra>
any kind of virtual dispatch always runs into this problem: what constraints does this method have that aren't reflected in its type?
05:49
<shu>
no, that's actually not what i'm saying
05:50
<shu>
but it's late, i don't think it's too important for me to be clear here for the proposal
05:51
<rbuckton>
set.intersection(new Set(array)), done
05:51
<snek>
i don't expect this at all
05:52
<rbuckton>
I don't expect this either. Maybe if the only requirement was that it was iterable, but not if we want intersection to be speedy.
05:52
<Justin Ridgewell>
ljharb: I dont' think that reasoning holds, because new Set(map) is useless
05:52
<Justin Ridgewell>
Just because something can create a set with elements doesn't mean it's appropriate for functions that receive sets.
05:52
<ljharb>
that's not the reasoning i used
05:52
<ljharb>
new Set(map) doesn't make a set that conceptually matches the input
05:53
<ljharb>
new Set(array) however does
05:53
<shu>
Michael Ficarra: but one last attempt: it's a public API evolution problem. if version 1 has one set of virtually dispatched methods, i think having version 2 where there's a new set of virtually dispatched methods where some of them conceptually overlap with the version 1 set of methods is Not Good
05:54
<rbuckton>
What if its: "If the argument is set-like use it like a set. If the argument is iterable, make a set from it and use that. Otherwise, throw"?
05:59
<Michael Ficarra>
rbuckton: and what makes something set-like?
06:00
<rbuckton>
Per the consensus, size (-ish), has(), and keys() I suppose.
06:03
<shu>
bakkot: you said you had wanted your proposal to be precedent setting. do you consider the result, which you disliked, to still be precedent setting (i.e. that we're sticking with naive string-named method duck typing)?
06:04
<Michael Ficarra>
I think the precedent-setting part was talking about where we put the symbols lol
06:04
<Michael Ficarra>
we didn't get that far
06:04
<shu>
that's what i'm asking
06:04
<shu>
do you consider this signal against protocols
06:04
<shu>
or do you consider it a one-off decision that they were a poor fit here
06:04
<bakkot>
well
06:04
<Michael Ficarra>
also with all the special casing we discussed, it would be hard to see this as precedent setting
06:04
<bakkot>
I want to not consider it precedent because I think it's a mistake
06:05
<shu>
then i look forward to the counterarguments for when protocols come back :)
06:05
<shu>
the arguments i heard from the other side seemed fairly general
06:05
<bakkot>
and intend to argue against using this design in the future in all the situations I'd argue against perpetuating any other historical mistake
06:05
<Michael Ficarra>
shu: no, the first-class protocols is primarily a facility for users to more easily create and consume protocols like the ones that are (sometimes) used by built-ins and syntax
06:06
<Michael Ficarra>
it is still good for users to do that
06:06
<bakkot>
yeah Symbol.iterator is still enough precedent for protocols
06:06
<bakkot>
Symbol.iterator was obviously good, I hope we are agreed?
06:06
<bakkot>
though I guess I should have asked waldemar or mark their opinions on it
06:06
<shu>
Michael Ficarra: okay, even if we do not apply it to builtins?
06:06
<Michael Ficarra>
even if we inconsistently apply it with built-ins, yes
06:07
<shu>
i see
06:07
<Michael Ficarra>
it's just as useful for building a healthy ecosystem
06:07
<shu>
i prefer nominal personally
06:07
<shu>
i agree with the need to signal a promise of conformance to some contract
06:08
<Michael Ficarra>
bakkot: I don't know what we agree on anymore
06:11
<shu>
i guess ron's idea is pretty much nominal
06:11
<bakkot>
we discussed this some at the end. I don't hate that option, but I do dislike that it has subtle performance characteristics; I would prefer to make the performance characteristics more explicit by making the user do the iteration of the iterable themselves
06:12
<shu>
i agree with that about explicit performance characteristics, unsurprisingly
06:12
<shu>
if we have nominal interface checking might as well just make it throw if it doesn't have it
06:13
<shu>
yes it's not JS-y but neither is having strong built-in behavior contracts?
06:15
<bakkot>
the "eagerly coerce values" behavior is one of the largest original sins of JS
06:15
<bakkot>
glad iterator helpers is at least starting to move away from that by guarding against NaN in take instead of just coercing it to zero, of all things, like slice does
06:16
<ljharb>
i'd expect erights would say the same about the "override mistake" and hidden intrinsics needing to be fixed instead of cargoculted forever
06:16
<Michael Ficarra>
bakkot: 🤫 you'll expose us
06:16
<bakkot>
override mistake is an original sin but nowhere near as large of one
06:17
<ljharb>
everyone has a sacred anticow they want to see slaughtered, and if we're condemned to repeat JS's mistakes forever, nobody'll be happy
06:17
<ljharb>
it makes much more sense to me to ack JS's mistakes and fix them wherever we feel we can get away with it
06:17
<shu>
override mistake is just a case of the world model implicit in the Old Scripture being lost
06:17
<shu>
i.e. prototypes being actually prototypical and designed to be cloned to make new instances
06:18
<shu>
instead of just being delegates
06:20
<nicolo-ribaudo>
The idea was that "new Foo" is "Foo.call({ ...Foo.prototype })"?
06:22
<shu>
yes
06:22
<shu>
https://en.wikipedia.org/wiki/Self_(programming_language)#:~:text=Instead%20of%20having,as%20prototypes.
06:22
<bakkot>
i agree with the need to signal a promise of conformance to some contract
wait if you agree with this why are you on board with the thing I said I was going to do
06:22
<bakkot>
that doesn't signal conformance at all
06:22
<bakkot>
or are you agreeing in general but not this specific case
06:23
<shu>
i agree in general not with symbol-based methods
06:23
<shu>
i also think the current pervasive string-named duck typing way does signal conformance, in a really shitty way
06:24
<shu>
time for sleep
07:07
<HE Shi-Jun>
i'd expect erights would say the same about the "override mistake" and hidden intrinsics needing to be fixed instead of cargoculted forever
What is "override mistake"?
07:14
<bakkot>
the thing where 'use strict'; let x = { __proto__: Object.freeze({ prop: 0 }) }; x.prop = 1; throws instead of assigning to a property on x shadowing the thing on the prototype
07:15
<ljharb>
iirc that if an inherited property is nonwritable, and you try to write to it, it throws
07:15
<ljharb>
is it proven to be web incompatible to change that? I’m assume it has
07:17
<bakkot>

in TDZ a while back Rob Palmer said

The override mistake is the biggest of all the mistakes I would like to see fixed. Igalia investigated this on our behalf 3 years ago (I think it may have been Joyee?) and found that Lodash relies on the exception thrown in the bad case.

07:17
<bakkot>
so presumably yes?
07:44
<littledan>
Btw is the bot magically doing better this month or do we still want a stenographer?
08:23
<nicolo-ribaudo>
I took notes for a few hours, and I still want a stenographer
08:41
<littledan>
Aside from the delegate naming issue, are there bot technologies that we should be adopting and haven’t done, that might improve the core accuracy of transcription ?
08:49
<nicolo-ribaudo>
The main problem I continue having is that the speech-to-text API we use doesn't work well if your English doesn't have a "common" accent, making it very hard to edit its transcription of non-native speakers (me included)
08:50
<nicolo-ribaudo>
But I don't think we can fix it in the bot
08:59
<Ashley Claymore>
For me it’s also that the bot is slower than the stenographer. For me to be of any use taking notes I have to add a 5-10 second delay to my audio. Which further means I can’t interact with what is happening.
11:35
<Anthony Bullard>
For me it’s also that the bot is slower than the stenographer. For me to be of any use taking notes I have to add a 5-10 second delay to my audio. Which further means I can’t interact with what is happening.
This is the worst part of note taking - barely being able to Fully process the presentation, let alone participate in the discussion
11:53
<littledan>
OK, thanks for the feedback, I will keep going with the request to Ecma.
12:31
<HE Shi-Jun>
the thing where 'use strict'; let x = { __proto__: Object.freeze({ prop: 0 }) }; x.prop = 1; throws instead of assigning to a property on x shadowing the thing on the prototype
So why this is "mistake"?
12:35
<HE Shi-Jun>
is it proven to be web incompatible to change that? I’m assume it has
I remember this was ES5 decision to align with getter/setter behavior, so seems no chance to change even we can go back ES6 era.
12:36
<littledan>
yes, this decision was made in the ES5 era
12:38
<HE Shi-Jun>

in TDZ a while back Rob Palmer said

The override mistake is the biggest of all the mistakes I would like to see fixed. Igalia investigated this on our behalf 3 years ago (I think it may have been Joyee?) and found that Lodash relies on the exception thrown in the bad case.

Still not get why this is the "biggest mistake"...
12:39
<littledan>
I guess that was a heavily qualified statement; other mistakes are sort of clearly not on a path to be fixed
12:39
<littledan>
(like, I'd love it if we could fix the mistake of typecasts all over the place...)
12:39
<littledan>
(and undefined casting to NaN in particular! that is literally the worst)
12:42
<Rob Palmer>
As the SES folk will tell you, the override mistake prevents simplistic freezing of all the primordials. Freezing the global object helps ensure robustness and opens up efficiencies for running semi-isolated tasks in the same runtime enviromnment. Whether this is the "biggest" mistake depends on your own personal value judgements. I have already made my peace with other "mistakes" like typeof null.
14:43
<Jack Works>
For example
14:44
<Jack Works>
After you freeze the Function.prototype, MyOldES5Class.toString = ... will be an error, which is very common in the ES5 era
14:45
<Jack Works>
If Function.prototype is not frozen, doing this will not change F.prototype.toString, but define a new own property on MyOldES5Class
15:14
<HE Shi-Jun>
But u still can use Object.defineProperty to add toString?
15:15
<ljharb>
you can, yes - but most code never uses that
15:16
<HE Shi-Jun>
Yeah, it requires u to change code, but if someone want to use SES, they very likely need to change some codes.
15:39
<Jack Works>
Unfortunately, it's not "change some code" most of the time, it's "patch node_modules".