01:05 | <Chris de Almeida> | please add yourself to the attendees list at the top of today's notes doc. (and yesterday's if you missed). thank you đ |
01:27 | <Chris de Almeida> | I captured the queue |
01:30 | <rkirsling> | 7 years, wow |
01:39 | <Ashley Claymore> | Fun co-incidence. The 'toSorted' spec bug was caught by a Japanese developer |
01:41 | <Jack Works> | "Summing a list is a very common operation and is one of the few remaining use cases for Array.prototype.reduce." |
01:41 | <Jack Works> | are we going to discouraging use of [].reduce? |
01:43 | <rkirsling> | no, because you don't necessarily want the new behavior |
01:43 | <jkup> | The reduce will be faster still, right? |
01:44 | <Michael Ficarra> | @jkup an equivalent loop will, at least |
01:44 | <Michael Ficarra> | but you REALLY don't want to do that |
01:44 | <Michael Ficarra> | your result can accumulate a ton of error |
01:44 | <Jack Works> | the wording sounds like reduce is a bad thing (actually yes in most cases it reduce the code readability) |
01:45 | <Jack Works> | but I'm not expecting that we should have a proposal to solve "the few remaining use cases of reduce", other motivations are ok thou |
01:46 | <rkirsling> | but you REALLY don't want to do that |
01:46 | <rkirsling> | just depends on the guarantees you're working with |
01:47 | <shu> | did you know reduce is pronounced re-doo-che |
01:47 | <Michael Ficarra> | @rkirsling if the number of values you're summing is small enough, the difference in perf between compensated and uncompensated is negligible anyway |
01:47 | <rkirsling> | touchĂŠ! |
01:47 | <Michael Ficarra> | and once it gets large enough to care about perf, you should also care about error accumulation |
01:47 | <Jack Works> | did you know reduce is pronounced re-doo-che |
01:48 | <rkirsling> | it is neither, it's just a "let's pronounce this word in a silly way" joke |
01:49 | <rkirsling> | ...the silly way in this case being like Italian, presumably :D |
01:53 | <Chris de Almeida> | the contents of the schedule may have shifted in flight. presenters please review and let us know if any issues |
01:54 | <bakkot> | The reduce will be faster still, right? sumPrecise can avoid a lot of work, which may make up for the difference |
01:58 | <hax (HE Shi-Jun)> | I feel setdefault is ok. Not sure why people prefer callback... |
01:58 | <ljharb> | because sometimes the default is expensive to compute. |
01:58 | <Michael Ficarra> | the callback can be lifted outside a loop, I'm not too worried about it |
01:58 | <Jack Works> | getOrSet |
01:58 | <bakkot> | it's true that people can avoid re-creating the callback, but they're not going to |
01:58 | <shu> | yeah |
01:59 | <ljharb> | i am also skeptical that prepending () => would have a noticeable perf hit, but have no way to argue that |
01:59 | <bakkot> | allocating throwaway closures is a lot more expensive than 0 |
01:59 | <shu> | it will have a noticeable perf hit in a hot loop for sure? |
01:59 | <shu> | allocation + call |
01:59 | <rbuckton> | allocating throwaway closures is a lot more expensive than
|
01:59 | <shu> | yeah people aren't gonna do that, i agree with kevin there |
01:59 | <shu> | people will write ()=>0 |
01:59 | <bakkot> | 100% of the time |
01:59 | <Michael Ficarra> | @shu @bakkot when it's [] , you're creating tons of thrown-away arrays instead of just not calling a callback |
02:00 | <shu> | when what is []? |
02:00 | <bakkot> | but at least you don't have to call anything |
02:00 | <ljharb> | in Iterator.concat the throwaway arrays were supposed to be nbd |
02:00 | <bakkot> | when what is []? |
02:00 | <Michael Ficarra> | people who care about perf already know to lift regexps outside of loops for example, this is the same thing |
02:00 | <hax (HE Shi-Jun)> | because sometimes the default is expensive to compute. map.set has similar issue? |
02:00 | <shu> | if the default value is [], presumably you want a different empty array? |
02:00 | <ljharb> | But current |
02:01 | <Michael Ficarra> | in Iterator.concat the throwaway arrays were supposed to be nbd |
02:01 | <hax (HE Shi-Jun)> | if the default value is [], presumably you want a different empty array? |
02:01 | <shu> | yes |
02:01 | <shu> | that's why i don't understand michael's point |
02:01 | <Eli Grey> | insert should be the value and use a getter for the function use case in emplace imo |
02:01 | <shu> | you can't have a single [] be the default |
02:01 | <shu> | unless you have copy-on-write [] |
02:01 | <Michael Ficarra> | @shu I'm talking about doing this operation in a loop |
02:02 | <shu> | how can you lift out a default [] out of a loop? |
02:02 | <shu> | you want all the default empty arrays to be the literal same array object, which can be mutated? |
02:02 | <Michael Ficarra> | @shu you can't, that's the point, you make it a callback and lift that out |
02:02 | <shu> | wat |
02:02 | <shu> | why would you make a callback at all |
02:02 | <shu> | setdefault(k, []) does the right thing? |
02:03 | <Michael Ficarra> | @shu it would be more performant |
02:03 | <shu> | what |
02:03 | <Jack Works> | (joke) I guess we have to materialize ParseNode.
|
02:03 | <shu> | are you saying doing a call on a const function that returns [] is faster than directly passing in []? |
02:03 | <Michael Ficarra> | a shared callback that is almost never called is more performant than tons of empty arrays that end up getting GC'd |
02:04 | <shu> | oh, i see, i missed the assumption that it's rarely a hit |
02:04 | <shu> | or, rarely a miss |
02:04 | <shu> | that depends on whether your loop mostly hits or mostly misses, right? |
02:04 | <ljharb> | that's the benefit of using a callback in the API as well; that the default fn would almost never be called, for when it's expensive |
02:04 | <Michael Ficarra> | correct @shu |
02:05 | <shu> | but a callback version would be more expensive when it is mostly misses |
02:05 | <shu> | so it 'just depends' |
02:05 | <Jack Works> | well, what react do is good, but bad |
02:05 | <Jack Works> | they call it when it is a function |
02:05 | <Anthony Bullard> | Is it not possible to do both? |
02:05 | <Michael Ficarra> | @ljharb they're worried that people will write the callback inline so instead we'll be creating tons of fresh functions that need to get GC'd |
02:05 | <Jack Works> | Is it not possible to do both? useState |
02:05 | <bakkot> | both is good |
02:05 | <Jack Works> | most cases it's good, some cases it's footgun |
02:05 | <shu> | yeah i'm fine with both |
02:05 | <Anthony Bullard> | I canât attend tonight, just following chat |
02:05 | <Michael Ficarra> | I'm fine with both |
02:06 | <ljharb> | both is fine too |
02:06 | <Anthony Bullard> | I guess I should say allow either |
02:06 | <shu> | computeIfAbsentViaThisCallbackHere |
02:06 | <ljharb> | i've called it getOrSetIfAbsent before but that name is horrible |
02:06 | <Michael Ficarra> | is that in Javaâ˘ď¸ 23? |
02:06 | <bakkot> | I like getOrInit or getOrInsert |
02:06 | <shu> | maybe getOrSetIfAbsentOrPresent |
02:07 | <bakkot> | the callback one is computeIfAbsent in java, which... works... |
02:07 | <Jack Works> | getWhenHasOrSetFromCallbackAndFinallyGetAgain |
02:07 | <Anthony Bullard> | I just meant the arg can be either a value or a function to return the value |
02:07 | <Anthony Bullard> | Obviously an issue if the value you want is a function |
02:08 | <Jack Works> | I just meant the arg can be either a value or a function to return the value |
02:08 | <bakkot> | oh, absolutely not that |
02:08 | <bakkot> | functions are valid values to store in a map |
02:08 | <hax (HE Shi-Jun)> | java have both:putIfAbsent ( = python setdefault), computeIfAbsent is callback version. |
02:08 | <Anthony Bullard> | But yeah emplace and emplaceWith |
02:08 | <Anthony Bullard> | Is better |
02:08 | <Jack Works> | functions are valid values to store in a map |
02:08 | <Michael Ficarra> | I just meant the arg can be either a value or a function to return the value |
02:09 | <Anthony Bullard> | WHY DO PEOPLE KEEP DOING THIS TO THEMSELVES?! |
02:09 | <Jack Works> | when you're in react and useState value might be a function, you do useState(() => fn) |
02:09 | <Anthony Bullard> | But other languages arenât afraid of having separate methods/functions for value args and function args |
02:10 | <Jack Works> | how do you like extractors |
02:10 | <bakkot> | java have both: putIfAbsent because it doesn't suggest that it gives you the current value in the case that it's present |
02:10 | <bakkot> | computeIfAbsent doesn't really either but I guess it's more obviously going to return something because "compute" suggests returning something |
02:10 | <Anthony Bullard> | Go for instance has many doSomething(arg1, value) doSomethingFunc(arg1, fn) pairs |
02:11 | <ljharb> | in ruby i think you'd have it take a block vs take a function, but most langs don't have blocks like that iirc |
02:11 | <Anthony Bullard> | The naming doesnât align obviously with ES style, but the pairing is fine and easy to grok |
02:12 | <Jack Works> | well naming is that hard, let's call it Map.prototype['007ae09e-b0e5-4939-b6f0-210e46f70538'] |
02:12 | <Eli Grey> | getters are good for this |
02:12 | <Anthony Bullard> | setDefault and setDefaultWith |
02:13 | <bakkot> | well naming is that hard, let's call it |
02:13 | <rkirsling> | lol |
02:13 | <Anthony Bullard> | advantage of this is that people will inevitably alias that string to something useful, and then we can just look at whatever name people are actually using |
02:13 | <rkirsling> | "delegated bikeshedding" |
02:13 | <Ashley Claymore> | "the masses have spoken" |
02:13 | <Anthony Bullard> | I think we have a new standard for APIs we canât name |
02:13 | <Jack Works> | advantage of this is that people will inevitably alias that string to something useful, and then we can just look at whatever name people are actually using |
02:14 | <Anthony Bullard> | Someone will still be mad about the UUID we chose |
02:14 | <hax (HE Shi-Jun)> | Map.set would return the value instead of the map itself 𤨠|
02:15 | <Michael Ficarra> | this reminds me, does delegate investigated similar utilities on npm? |
02:15 | <Jack Works> | Someone will still be mad about the UUID we chose |
02:15 | <Jack Works> | I think people mostly just do this pattern inline rather than rely on an npm package for it is-odd on npm so definitely we'll have emplace on npm |
02:16 | <hax (HE Shi-Jun)> | in ruby i think you'd have it take a block vs take a function, but most langs don't have blocks like that iirc |
02:16 | <ljharb> | not that i know of |
02:16 | <Jack Works> | Really hope JS can have block. Does "Block param" proposal still alive? |
02:16 | <Jack Works> | it contains context and can be executed right? |
02:17 | <Anthony Bullard> | Really hope JS can have block. Does "Block param" proposal still alive? |
02:18 | <Jack Works> | Neither a ruby or smalltalk guy, whatâs the advantage of blocks? IMO mostly syntax sugar, may look like
|
02:18 | <Anthony Bullard> |
|
02:21 | <ljharb> | but it doesn't have a function stack frame/overhead, ideally |
02:21 | <hax (HE Shi-Jun)> | The difference between the arrow function and real block may be the real block might support non-local jump (I believe block param proposal has the issue to discuss that, also do expression proposal) |
02:22 | <Anthony Bullard> | but it doesn't have a function stack frame/overhead, ideally |
02:23 | <ljharb> | it does close over things, true |
02:23 | <Jack Works> | The difference between the arrow function and real block may be the real block might support non-local jump (I believe block param proposal has the issue to discuss that, also do expression proposal) |
02:24 | <Anthony Bullard> | In Kotlin { it + 1 } just desugars to (X) -> X + 1 |
02:24 | <Michael Ficarra> | non-local jump sound worse |
02:25 | <bakkot> | huh apparently safari tech preview is already shipping Math.sumPrecise, nice |
02:25 | <bakkot> | unfortunately a port of my dumb polyfill to C++ instead of something faster |
02:25 | <Jack Works> | tell that to the people who want do expressions to have it return/break/continue |
02:25 | <hax (HE Shi-Jun)> | non-local jump sound worse a.map { if (it != null) compute(it); else break } |
02:26 | <hax (HE Shi-Jun)> | I also against do expression with |
02:26 | <bakkot> | unfortunately a port of my dumb polyfill to C++ instead of something faster |
02:26 | <Michael Ficarra> | I also against do expression with |
02:26 | <bakkot> | also they don't have a fast-path for "array of all numbers" which, I don't know if JSC has a concept of "array of all numbers" |
02:26 | <Anthony Bullard> | maybe i am wrong about that. I mean something like |
02:27 | <bakkot> | (sumPrecise was designed to avoid any user code in the hot loop specifically so that you could have that optimization) |
02:27 | <rkirsling> | this is a very good question and a very good answer |
02:28 | <Michael Ficarra> | So you want a loop, but make it feel functional? |
02:29 | <hax (HE Shi-Jun)> | So you want a loop, but make it feel functional? |
02:30 | <Jack Works> |
|
02:30 | <Chris de Almeida> | ljharb: help me understand better stack trace there? that sounds harder to debug |
02:31 | <ljharb> | currently it gives a stack trace that points to the validation function, and then below that, the validator callsite. there's a possibility for a clearer error imo that points to the function signature and references extractors in the message |
02:31 | <Chris de Almeida> | hmm |
02:31 | <Anthony Bullard> | As I understand, block param proposal has the motivation to make JS more DSL friendly. As such motivate, I say yes. |
02:33 | <hax (HE Shi-Jun)> | more like "you want reduce but you want to call it map" map to something else , eg. collect ? đ |
02:39 | <Anthony Bullard> | Is it just me (not on the call), but when the chat dies out suddenly, do you wonder if Matrix just tipped over or was there a break? |
02:41 | <ptomato> | or everyone is paying real close attention to the slides... |
02:41 | <Rob Palmer> | Syntactically correct TypeScript will emit JS even if the type checks fail. (And sometimes it will emit JS even if the syntax is invalid.) |
02:42 | <shu> | right |
02:42 | <shu> | but that doesn't conflict with what i'm asking |
02:46 | <hax (HE Shi-Jun)> | Syntactically correct TypeScript will emit JS even if the type checks fail. (And sometimes it will emit JS even if the syntax is invalid.) import {x} "path" (missing from ) still work in ts... |
02:47 | <Rob Palmer> | My favourite is automatic brace insertion in ts. |
02:47 | <canadahonk> | My favourite is automatic brace insertion in ts. |
02:48 | <Rob Palmer> | (sorry this is a distraction from current topic - it should be in TDZ) |
02:48 | <danielrosenwasser> | if you write
TypeScript gracefully recovers parsing, tells you you forgot a brace, and just re-prints it the right way
|
02:48 | <Anthony Bullard> | My favourite is automatic brace insertion in ts. |
02:57 | <Ashley Claymore> | Found this one recently. TS supports Python scoping
|
02:58 | <danielrosenwasser> |
|
02:59 | <danielrosenwasser> | Or I'll file a bug if I can |
02:59 | <danielrosenwasser> | Either way nice find! |
03:00 | <Ashley Claymore> | will do! |
03:01 | <bakkot> | .... what do you even do about that case |
03:01 | <bakkot> | parse error, I guess? |
03:02 | <danielrosenwasser> | possibly - we'd probably do it at checking, it gets treated more like an early error |
03:02 | <Rob Palmer> | it's a graceful parser |
03:02 | <littledan> | Seems like we should have more discussions in TC39 about the architectures of various implementations, both tools and native |
03:03 | <littledan> | Like presentations explaining this |
03:04 | <Michael Ficarra> | @danielrosenwasser allow it, add a grammar alternative like Statement : TypeDeclaration Statement |
03:04 | <danielrosenwasser> | lmao |
03:04 | <Michael Ficarra> | đď¸ this is my serious face |
03:04 | <danielrosenwasser> | Statement :: Statement Statement |
03:06 | <danielrosenwasser> | Likewise, I think it could be helpful to see concretely what the performance concerns are, why certain optimizations are difficult for engine implementers, etc. |
03:06 | <littledan> | Yeah this feature is as expensive as a method call + array destructuring; I understand the concern about array destructuring being expensive but I donât know what else engines are imagining that tools would do |
03:07 | <littledan> | I dont think we should block all features where people have posited impractical optimizations. We certainly would not have done iterator helpers if that were a requirement |
03:08 | <Ashley Claymore> | Can you file a bug? |
03:10 | <danielrosenwasser> | But I think there's a legitimate "pit of despair" concern. Like imagine you are writing a tool that you want to be reasonably fast and you posit that pattern matching should be as fast as a switch on the class or something like that |
03:20 | <keith_miller> | I think the concern here is that we're (potentially) offering a very clean but expensive abstraction/idiom that people are trained from other languages to be zero-cost. |
03:21 | <keith_miller> | If this idiom is no worse in terms of performance than what people would do otherwise then I'm not concerned |
03:22 | <keith_miller> | But I think adding or encouraging idioms that have known to be bad performance isn't in browser user's interest and that's what I'm trying to reflect. |
03:23 | <rbuckton> | Summary has been added. |
03:24 | <rbuckton> | If this idiom is no worse in terms of performance than what people would do otherwise then I'm not concerned const Point(x, y) = p is no more expensive than const [x, y] = Point[Symbol.customMatcher](p, "list") |
03:25 | <rbuckton> | though if we end up not finding a solution to iterator destructuring performance and end up going with array-as-object destructuring, const Point(x, y) = p is potentially faster |
03:25 | <keith_miller> | But it might be more expensive than: if (p instanceof Point) { let x = p.x; let y = p.y ...} |
03:25 | <keith_miller> | So that's the bar to compare against |
03:27 | <keith_miller> | And devs just might structure their code differently without this, potentially in a way that's more performant. I'm saying that I want to be convinced they're not. |
03:27 | <rbuckton> | That doesn't have the expressivity we're seeking. The motivations include custom validation. |
03:27 | <rbuckton> | The Point example from my slides used brand checking via private names |
03:28 | <keith_miller> | That's a bummer and I would like to have that validation too but not really my concern, unfortunately. |
03:28 | <littledan> | I understand the performance concern âthis will encourage people to use more array destructuringâ. There are a number of possible remedies to that |
03:30 | <littledan> | One is using this alternative Array-like destructuring semantics, as Ron mentioned. If we want to avoid the allocation altogether, we could also limit extractors to a single argument, and then any nested array destructuring would be explicit. |
03:30 | <keith_miller> | It's not just the array destructuring although that's part of the concern. It's if the idiom makes sense as a whole. |
03:30 | <littledan> | The discussion got a bit abstract as to which performance concerns people had. What other ones were there apart from array destructuring cost? |
03:31 | <littledan> | Or whether the idiom makes sense⌠it is really common across languages and I have found it useful, so I am wondering if people can make their concerns more concrete. |
03:32 | <keith_miller> | What other dynamic languages have this? |
03:32 | <littledan> | Pattern matching/extractors are definitely not linked to static typing. Python and Racket have versions |
03:32 | <rbuckton> | Python, though they do something slightly different that the pattern matching champions group does not agree with. |
03:32 | <littledan> | It is just random cultural history that they are linked to functional/statically typed languages |
03:33 | <littledan> | Erlang is dynamically typed and does tons of pattern matching |
03:33 | <littledan> | Prolog for that matter, untyped and the ancestor of a lot of these ideas |
03:35 | <littledan> | Elixir https://hexdocs.pm/elixir/pattern-matching.html#the-match-operator |
03:35 | <keith_miller> | But are those idioms performant in those languages? Or are they just a cost people are willing to pay for convenience? |
03:35 | <rbuckton> | Its not really a static vs dynamic language feature. C# uses Deconstruct() for custom extraction, and static type information to do overload disambiguation and argument matching, but compared to this the main difference is that C# uses out parameters, which we don't have, rather than something like iterator destructuring. |
03:37 | <keith_miller> | I'm not debating the convenience of the idiom. Only its potential performance impact with use. |
03:38 | <littledan> | I havenât heard anyone talk about pattern matching as an expensive feature outside of the array destructuring issue in any other language. Some functional statically typed languages do fancy things optimizing trees of conditionals for pattern matching but others donât. |
03:38 | <rbuckton> | The pattern matching proposal has some interesting mechanisms it plans to employ related to caching that have the side benefit of improving performance in a disjunction or multiple match-legs. |
03:39 | <keith_miller> | Then that should make proving it's performant easy! |
03:39 | <keith_miller> | I'm not saying it's not performant only that I'd like to see non-trivial real world use cases benchmarked. |
03:39 | <rbuckton> | So in pattern matching something like :
could potentially only evaluate the custom matcher once and reuse the extracted elements on both match legs. |
03:40 | <littledan> | Ruby pattern matching: https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html |
03:42 | <littledan> | I'm not saying it's not performant only that I'd like to see non-trivial real world use cases benchmarked. |
03:42 | <rbuckton> | Pattern matching caching is something I'm not looking forward to desugaring mostly due to the emit size of the desugaring. I'm hoping I can stash a lot of it in emit helpers in tslib to cut down on bundle size. |
03:44 | <littledan> |
|
03:44 | <littledan> | And the >0 syntax is a whole other topic! |
03:45 | <rbuckton> | It's not part of the core proposal, to be clear. Its something I'd like to see but we're pushing it to a follow-on. |
03:45 | <rbuckton> | It's extremely useful in C# |
03:50 | <littledan> | If array destructuring is expensive and impractical to optimize, should we in TC39 be discouraging its use? For example, by encouraging transpilers to transform it into object destructuring (treating it as array-like)? |
03:51 | <littledan> | I donât like this idea personally but if this is such a big problem that we canât build other features on it⌠|
04:00 | <bakkot> | yes, code which cares about performance does specifically write { 0: foo, 1: bar } = instead of [foo, bar] = |
04:00 | <bakkot> | transpilers can't do this without type information |
04:01 | <Ashley Claymore> | I wonder if it be web-compat, and also more performant, to change iterator destructuring to be specced as property access if the RHS passes Array.isArray ? i.e. assume the array's iterator will be the default one |
04:01 | <rbuckton> | It's significantly faster to do const { 0: x, 1: setX } = useState() in React, but its rare to see that done. |
04:02 | <keith_miller> | That's an interesting idea! No idea if it's compatible though. |
04:02 | <bakkot> | I wonder if it be web-compat, and also more performant, to change iterator destructuring to be specced as property access if the RHS passes |
04:02 | <bakkot> | though it might need to be "isArray and also not a proxy", potentially |
04:02 | <bakkot> | proxies :( |
04:03 | <canadahonk> | I do basically this internally (sorry spec) |
04:04 | <canadahonk> | it definitely fails some test262 tests though |
04:04 | <rbuckton> | How many people use for..of over arrays today? I assume that still isn't optimized for Array vs other iterators. |
04:05 | <bakkot> | I am almost certain that's optimized in JSC, at least |
04:05 | <bakkot> | and would kind of expect it to be in V8 but it's been a while since I looked |
04:05 | <shu> | we suck at it still i think |
04:06 | <rbuckton> | If you can optimize for..of why not const [x, y] = ? |
04:07 | <shu> | we can do something for const [x,y] probably, but it's not going to be parity with object destructuring, will have a perf cliff for non-Arrays and a bunch of other bailout paths (which is also a increased attack surface) |
04:07 | <shu> | there're a lot of undesirables hidden behind "why not optimize this other pattern" |
04:09 | <rbuckton> | I expect most destructuring is array to array, but I don't have metrics to back that up. |
04:09 | <rbuckton> | I'd be perfectly happy with Array being fast and other iterators being slower, since the alternative is both are slower. |
04:10 | <shu> | yeah i agree it's worth optimizing that? |
04:10 | <rbuckton> | React alone should be enough of a reason to optimize array to array destructuring, but I'm working on some benchmarking to get an understanding of the actual effect it has. |
04:11 | <keith_miller> | It is very optimized in JSC (modulo the iterator object itself being allocated) |
04:11 | <Rob Palmer> | I thought V8 had already done that |
04:11 | <justingrant> | 7 years, wow |
04:11 | <shu> | i don't actually know, lemme see |
04:11 | <littledan> | Yes they canâtsc does it in some emit modes unconditionally! (When emitting es5) |
04:12 | <bakkot> | sorry, without also breaking some other code |
04:12 | <Jack Works> | How many people use for..of even it might be slow. readibility > performance when the code is not in a hot path |
04:12 | <Ashley Claymore> | https://docs.google.com/document/d/1hWb-lQW4NSG9yRpyyiAA_9Ktytd5lypLnVLhPX9vamE/edit?tab=t.0#heading=h.9ss45aibqpw2 |
04:12 | <rbuckton> | TSC only does that for --target ES5 where there is no expectation of Symbol.iterator . |
04:12 | <littledan> | sorry, without also breaking some other code |
04:12 | <rbuckton> | And we have --downevelIteration to emulate actual ES2015+ semantics. |
04:13 | <littledan> | Yes sorry that wasnât meant as a tsc critique |
04:13 | <littledan> | But generally: if we want transpilers to do unsound things (like around TDZ) that is something we as a committee can say |
04:14 | <rbuckton> | Even in the --downlevelIteration case we use a runtime helper to emulate an iterator over an array, rather than bake that into the actual loop. |
04:14 | <rbuckton> | so the emit remains the same regardless as to the type of the iterated object |
04:14 | <shu> | https://docs.google.com/document/d/1hWb-lQW4NSG9yRpyyiAA_9Ktytd5lypLnVLhPX9vamE/edit?tab=t.0#heading=h.9ss45aibqpw2 |
04:14 | <littledan> | I dunno if we should do such unsound downlevelings but I donât know what else would actually meet what the browsers seem to be expecting |
04:14 | <shu> | the quickest way to make sure that happens is to make it show up in speedometer or the new jetstream |
04:15 | <Ashley Claymore> | is it a really bad idea to have a 3rd form of destructuring for array-like?
|
04:16 | <keith_miller> | The expectation is that const Point(x, y) = p isn't more expensive than that const Optional.Some(Point.2D(x, y)) = o would likely decode to 20-30 byte codes in JSC |
04:16 | <rbuckton> | let |a, is ambiguous |
04:17 | <Ashley Claymore> | one R&T design was [| a, b, c |] , maybe could be more like that? |
04:18 | <ljharb> | Sorry getting back to this but while yes const [x, y] = Optional.some[Symbol.customMatcher](Point[Symbol.customMatcher](p, 'list'), 'list'); ? |
04:18 | <shu> | i'll be somewhat blunt: i continue to see the line of argument from extractor-proponents to be "for these technical reasons it's unrealistic to do this in tools" that's fine! but that doesn't imply "engines will do it" |
04:18 | <shu> | i think the counterfactual that "people will write things that are even slower" is also just not true in this case, because pattern matching and extractors don't exist? |
04:19 | <ljharb> | the things those will be used for are already done, just in other ways |
04:19 | <shu> | and if they don't want to write that verbose example that jordan posted above, that's good! the grossness of the example correlates with the slowness |
04:19 | <ljharb> | pattern matching is done with function calls and if/else and/or switch, extractors with separate function calls |
04:19 | <shu> | that seems good to me |
04:19 | <shu> | their verbosity gives a hint to the work they're doing |
04:20 | <ljharb> | i'm not sure the point of programming languages is to have verbosity correlate to cost? |
04:20 | <nicolo-ribaudo> | i'll be somewhat blunt: i continue to see the line of argument from extractor-proponents to be "for these technical reasons it's unrealistic to do this in tools" |
04:20 | <rbuckton> | Pattern matching results in far more readable code than the current approach. |
04:20 | <shu> | if a terser and more readable thing can be a near zero-cost abstraction, that's great |
04:20 | <rbuckton> | The verbosity makes it harder to reason over. |
04:20 | <shu> | if it can't be, we gave our position yesterday on the cost to users |
04:21 | <Bradford Smith> | My concern with Extractors is that they seem overly clever to me. They hide what's happening from the developer too much, leading them to incorrect ideas about how expensive they are. |
04:21 | <shu> | i'm not sure the point of programming languages is to have verbosity correlate to cost? |
04:21 | <ljharb> | indeed |
04:21 | <rbuckton> | pattern matching can be more efficient than the alternative if we have sufficient caching and reuse across multiple branches of the pattern. |
04:21 | <keith_miller> | Sure but that's still 48 byte codes in JSC today:
|
04:21 | <ljharb> | and readable code correlates to that value, imo often more highly than the performance of that application |
04:21 | <shu> | i disagree so strongly on that point |
04:22 | <ljharb> | that is clear :-) |
04:23 | <bakkot> | I might believe that claim in C, which is hard to write correctly and where bugs can do arbitrarily bad things, but I certainly do not agree with that claim for web apps written in JS |
04:24 | <keith_miller> | I might believe that claim in C, which is hard to write correctly and where bugs can do arbitrarily bad things, but I certainly do not agree with that claim for web apps written in JS |
04:24 | <ljharb> | it's not a claim that it's always the case, to be clear, and obv some threshold of slowness will always cancel out the other benefits. |
04:24 | <keith_miller> | Which is a lot by JSC standards |
04:24 | <keith_miller> | This function would be invalid for inlining from one binding alone |
04:25 | <bakkot> | I am agreeing with shu |
04:26 | <bakkot> | I think that webapps being slow is the cause of much more pain than webapps being unclear to their maintainers |
04:26 | <keith_miller> | why not to |
04:27 | <keith_miller> | From one statement |
04:27 | <keith_miller> | Which I don't think devs would expect |
04:28 | <rbuckton> | JSC inlining is limited to the statement level? |
04:28 | <keith_miller> | It's limited by the number of bytes in the instruction stream |
04:28 | <keith_miller> | IIRC, it's 170 bytes |
04:30 | <Michael Ficarra> |
const Array(a, b, c) = ... ? |
04:31 | <rbuckton> | If extractors end up needing to use array-as-object destructuring, then yeah, that's a possibility. |
04:33 | <keith_miller> | A lot of that is resolving the various properties needed though not the array destructuring |
04:34 | <keith_miller> | I encourage you to look at that bytecode sequence and really think about all the subtle work that has to happen to resolve that binding. |
04:35 | <shu> | i feel like folks haven't really internalized the "complexity is moved, not removed" point we tried to make yet |
04:36 | <rbuckton> | And the bytecode for const [[[x, y]]] = foo given it results in three lookups to Symbol.iterator ? I understand extractors do that as well, I'm just curious. |
04:36 | <Michael Ficarra> | @shu this could literally be a special form that does remove the complexity, different from const window.Array(a, b, c) = ... |
04:37 | <keith_miller> | const [[[x, y]]] = foo bb#1 bb#2 bb#3 bb#4 bb#5 bb#6 bb#7 bb#8 bb#9 bb#10 bb#11 bb#12 bb#13 bb#14 bb#15 bb#16 bb#17 bb#18 bb#19 bb#20 bb#21 bb#22 Identifiers: Constants: |
04:37 | <Michael Ficarra> | please don't dump walls of text into Matrix, make a gist or something |
04:38 | <keith_miller> | I put it in a thread for that reason? |
04:39 | <rbuckton> | Does the bytecode for the Optional.some[Symbol.customMatcher] include the cost of looking up customMatcher on Symbol? A native implementation would be able to avoid that because it would be using a known symbol. |
04:39 | <Michael Ficarra> | I put it in a thread for that reason? |
04:40 | <keith_miller> | oh I think my client doesn't do threads |
04:40 | <hax (HE Shi-Jun)> | and readable code correlates to that value, imo often more highly than the performance of that application |
04:40 | <Jack Works> | Does the bytecode for the |
04:40 | <keith_miller> | Sure, that would be avoided but that's not too much of the code generated |
04:46 | <keith_miller> | I think the browser vendors are pushing back on the idea that it gives you perf |
04:46 | <keith_miller> | It's not a magic box where things become faster because you want it to |
04:46 | <rbuckton> | At least extractors are not a hidden cost you stumble into, unlike getters/setters or let/const TDZ. You don't pay the cost if you don't use extractors, and so long as developers are aware of the cost (and that cost is not absurdly high), developers can balance the pros and cons and fall back to existing behaviors for high performance scenarios. I think part of concern is that developers might blindly adopt extractors without considering the cost? |
04:46 | <Justin Ridgewell> | oh I think my client doesn't do threads |
04:46 | <shu> | i think extractors are totally a hidden cost |
04:47 | <yulia> | At least extractors are not a hidden cost you stumble into, unlike getters/setters or let/const TDZ. You don't pay the cost if you don't use extractors, and so long as developers are aware of the cost (and that cost is not absurdly high), developers can balance the pros and cons and fall back to existing behaviors for high performance scenarios. I think part of concern is that developers might blindly adopt extractors without considering the cost? |
04:47 | <shu> | here's a really simple, clean looking code (multiple delegates have said as such, i also think it looks very clean and nice) that hides a pretty expensive operation that doesn't exist in other languages that inspired this feature! |
04:47 | <Michael Ficarra> | @yulia no more so than positional destructuring |
04:47 | <keith_miller> | Yeah the syntax is đŻ hiding the cost! That's exactly what I was trying to show! |
04:47 | <rbuckton> | The syntax looks like a function call, part of the benefit of that is that the expectation is that it will have the cost of a function call. |
04:48 | <shu> | do you think a rust or haskell programmer look at pattern matching and think that's a function call? |
04:48 | <canadahonk> | couldn't the same be said with array destructuring? |
04:48 | <bakkot> | yes |
04:48 | <shu> | yeah? |
04:48 | <yulia> | yes, |
04:48 | <shu> | array destructuring is terrible |
04:48 | <canadahonk> | welp |
04:48 | <keith_miller> | @yulia no more so than positional destructuring |
04:48 | <hax (HE Shi-Jun)> | A function calling is also a very simple syntax (and can hide cost). I don't see there is any diff. |
04:49 | <keith_miller> | In every language a function call is a significant cost |
04:50 | <keith_miller> | Maybe if you're clever you can get the compiler to remove a lot of that but IMO devs know that's on them to verify |
04:50 | <Aki> | "other parts of the web platform" /me perks up |
04:50 | <Chris de Almeida> | the good parts or... ? |
04:51 | <Marja HÜlttä> | function calls and things like array destructing / extractors are also completely different levels of fundamental; can't really imagine a modern language without functions, but the other 2 are much more optional |
04:51 | <rkirsling> | amusing overload of "javascript core" lol |
04:51 | <rkirsling> | (yes it was clear in context hehe) |
04:51 | <keith_miller> | Yeah, I got really confused for a sec lol |
04:51 | <yulia> | sooorrryyyy my brain is so dead |
04:51 | <rbuckton> | Maybe if you're clever you can get the compiler to remove a lot of that but IMO devs know that's on them to verify const p = Point(x, y) has a cost, they won't be expected to know that const Point(x, y) = p does as well? |
04:51 | <Bradford Smith> | Also, there is no restriction in the Extractors proposal on just how expensive that function may be. It could do anything. The examples assume they will always "undo" a constructor call, but there's no reason to believe it would stay restricted to that in practice. |
04:52 | <rbuckton> | That's part of the reason for the duality of the syntax. Extraction mirrors application. |
04:52 | <Bradford Smith> | only by convention, though. It's not enforceable. |
04:52 | <rbuckton> | application can be arbitrarily expensive because its user code. Extraction can be arbitrarily expensive because its user code. |
04:53 | <keith_miller> | No because other bindings in the language don't have a cost. let/const is a great example of this in the sense that people didn't expect there would be a cost there. |
04:53 | <hax (HE Shi-Jun)> | If a specific extracting logic is complex and cost , then it always there, people just write it in some other form, and generally speaking, average programmers normally write much slower code repeatly and every place. On the other side, extractor allow senior programmer factor the logic and do optimization in single place and provide other an easy to adoption syntax. |
04:53 | <Bradford Smith> | My point is, part of the assumption of improved readability is assuming that the feature will be used in a particular way. I expect it would be abused to make code "magically" shorter. |
04:54 | <rkirsling> | ngl if I'm in JS author mode, my brain wants to view destructuring as zero-cost |
04:54 | <rbuckton> | No because other bindings in the language don't have a cost. let/const is a great example of this in the sense that people didn't expect there would be a cost there. const [x, y] has a cost. Extractors have an obvious cost because they are explicitly designed to run user code, that's the whole point. |
04:55 | <keith_miller> | I think it's non-obvious. Maybe this would be worth a developer study? |
04:55 | <rbuckton> | Most developers don't think about iteration cost when they use const [x, y] because the possibility of iteration being expensive is hidden on the RHS, not the LHS. Extractors put that cost in your face by being on the LHS. |
04:55 | <hax (HE Shi-Jun)> | ngl if I'm in JS author mode, my brain wants to view destructuring as zero-cost |
04:55 | <keith_miller> | IIRC, Mozilla (not asking them to do it again) did this in the past and it revealed a lot of interesting insights. |
04:57 | <yulia> | (we did what now?) |
04:58 | <yulia> | ... user study? yeah thats something we have a whole TG for please get in touch! |
04:58 | <shu> | user study for this hidden cost question |
04:58 | <yulia> | we can get students to do it |
04:58 | <yulia> | (im not doing it, no time these days, but there are eager folks) |
04:59 | <rbuckton> | That could be very helpful, though I'm not sure how to get that process started. |
04:59 | <yulia> | you can make an issue in https://github.com/tc39/tg5/issues or add it here: https://github.com/tc39/tg5/issues/29 |
05:00 | <yulia> | then at our next meeting we will bring it up as a request for help from the committee, and we will see if one of the universities wants to take it up |
05:02 | <rbuckton> | Thanks, I'll look into this after plenary. |
05:07 | <Michael Ficarra> | hot take: I'm kinda okay with engine divergence on stupid stuff that nobody should ever be observing |
05:07 | <Michael Ficarra> | maybe that's a lukewarm take, I dunno |
05:08 | <Ashley Claymore> | it's like natural fuzz testing of apps |
05:14 | <shu> | i think this is a ArrayBuffer-specific thing |
05:14 | <shu> | like in general deviance is particularly bad for AB and TAs because of the whole Khronos thing |
05:15 | <rbuckton> | Only stage 4 candidate of the day, there were like 4 yesterday |
05:16 | <keith_miller> | Yeah AB is a pants on head crazy place |
05:16 | <rkirsling> | detach all the things |
05:16 | <shu> | in particular that bug from the presentation is because what used to be a ToInteger changed to a ToIndex sometime in 2016 |
05:16 | <shu> | https://github.com/tc39/ecma262/pull/410 |
05:16 | <Chris de Almeida> | Only stage 4 candidate of the day, there were like 4 yesterday |
05:17 | <shu> | like, it looks like SM was intimately involved with that PR at the time, which is probably why they're compliant |
05:17 | <shu> | and this just never got implemented in JSC and V8 for whatever reason at the time |
05:17 | <shu> | hot take: I'm kinda okay with engine divergence on stupid stuff that nobody should ever be observing |
05:22 | <nicolo-ribaudo> | I was talking with an MDN writer -- I think we should make MDN a stage 4 requirement. MDN is very happy to write docs by themselves, but we don't really have a process to coordinate. Their current process is "regularly check what Firefox implements", which means that sometimes Stage 4 proposals (thus, meant to be used by developers) have no docs |
05:23 | <yulia> | we have a meta issue for all tc39 proposals |
05:23 | <yulia> | https://bugzilla.mozilla.org/show_bug.cgi?id=1435811 |
05:23 | <yulia> | and each proposal (now) has a meta that documentation watches |
05:24 | <ryzokuken> | I was talking with an MDN writer -- I think we should make MDN a stage 4 requirement. MDN is very happy to write docs by themselves, but we don't really have a process to coordinate. Their current process is "regularly check what Firefox implements", which means that sometimes Stage 4 proposals (thus, meant to be used by developers) have no docs |
05:24 | <Michael Ficarra> | I was talking with an MDN writer -- I think we should make MDN a stage 4 requirement. MDN is very happy to write docs by themselves, but we don't really have a process to coordinate. Their current process is "regularly check what Firefox implements", which means that sometimes Stage 4 proposals (thus, meant to be used by developers) have no docs |
05:24 | <ryzokuken> | and not at Stage 4 |
05:25 | <ryzokuken> | so yeah this is not unprecedented and we just need to bring it to agenda to get into the process doc I guess |
05:25 | <Andreu Botella (at TC39, đ JST)> | we can't make something a requirement if it is entirely out of our control |
05:25 | <nicolo-ribaudo> | and each proposal (now) has a meta that documentation watches |
05:26 | <yulia> | yep, thats true -- was giving some insight about how the process currently works |
05:26 | <yulia> | we don't actually tell MDN what to write about, and sometimes they write docs before we ship |
05:26 | <nicolo-ribaudo> | we can't make something a requirement if it is entirely out of our control |
05:26 | <yulia> | they just watch that issue for upcoming topics |
05:26 | <yulia> | and we have a meta issue for every proposal at stage 3 |
05:27 | <Michael Ficarra> | True, their recommendation was actually "require that MDN folks have been notified in advance so that they can make sure to prioritise docs" |
05:27 | <Chris de Almeida> | while I very much want the docs, I am wary of asking more from proposal champions |
05:27 | <Michael Ficarra> | MDN is a github repo |
05:28 | <nicolo-ribaudo> | while I very much want the docs, I am wary of asking more from proposal champions |
05:28 | <Chris de Almeida> | then it doesn't seem like we can require it |
05:28 | <nicolo-ribaudo> | Well, HTML for example requires that a docs issue must have been opened before merging the change to the spec |
05:29 | <yulia> | nicolo-ribaudo: which proposals were missed? |
05:29 | <Michael Ficarra> | yeah I am fine with asking for an issue to be opened or something akin to that |
05:30 | <Chris de Almeida> | I am fine with the spirit of it, but I hesitate to codify something 3rd party. but if everyone supports it, I won't get in the way |
05:30 | <nicolo-ribaudo> | nicolo-ribaudo: which proposals were missed? |
05:31 | <ptomato> | a coworker and I tried to get ahead of the game with Temporal docs for MDN, back when the proposal went to stage 3. it was a frustrating experience because it was blocked for months on getting a Temporal key into the browser compatibility data repo. I had to conclude that the process wasn't really navigable for outsiders. I don't think we can really require it from our side |
05:32 | <shu> | waldemar: it's not a full pre-parse phase, it's an eager, regular parse phase. pre-parse = parse for syntax errors, do not generate an AST, do not generate bytecode. regular parse = parse, generate an AST, and bytecode. since pre-parse is default, it turns out slower for a function that's immediately executed to first pre-parse, then to do a full parse. so this is a hint to say "skip that initial pre-parse, because it's gonna be called immediately" |
05:33 | <shu> | ah, i completely anticipated the wrong question waldemar, apologies |
05:45 | <nicolo-ribaudo> | â ď¸ Remember that this room is public |
05:45 | <Chris de Almeida> | yes, do not discuss topic here, or anywhere in matrix for that matter |
05:46 | <Aki> | /set mode +m |
05:47 | <Rob Palmer> | Due to explicit lazy-loading, our system lends itself to loading code that is highly likely to be executed. Prior to us rolling out client-side code-caching, we found maximal PIFEs sped up app load times. The marginal cost of the unnecessary preparse was costing a lot (>100ms.). I believe the need for those legacy-style hints went away after we switch to bytecode caching with high hit rates (90%+ of modules hit the cache). But for cache misses, I would expect the source hints to still be valuable. |
05:48 | <rkirsling> | what is the point of void there (this question should be separate from the topic, I assume) |
05:53 | <hax (HE Shi-Jun)> | what is the point of |
05:54 | <rkirsling> | yeah, I guess so |
05:54 | <hax (HE Shi-Jun)> | what's the behavior ofseal and freeze on resizeable typed array? |
05:54 | <hax (HE Shi-Jun)> | I remember freeze just throw? |
05:55 | <hax (HE Shi-Jun)> | so another option is just throw? |
05:57 | <Chris de Almeida> | 𤍠|
06:29 | <Ashley Claymore> | what is the point of |
06:34 | <rkirsling> | hah! |
06:34 | <rkirsling> | I just couldn't wait ;) |
06:35 | <rkirsling> | that'd be an awfully large needs-consensus PR methinks |
06:36 | <Michael Ficarra> | yeah there's no way that could be done as a needs-consensus PR |
06:47 | <littledan> | itâs not just linters: if you use VS Code, then you will immediately get things marked if they are unused, kinda like a soft error, and with void, you wouldnât get it marked. I guess tools could learn a convention like _a and do the same. |
06:49 | <ljharb> | TS also warns on it unless you follow their nonconfigurable convention |
06:50 | <nicolo-ribaudo> | All of this shows that we made a mistake in the design of using |
06:53 | <Jack Works> | this is what pattern matching explained why a void is better |
06:54 | <hax (HE Shi-Jun)> | Though I guess pattern matching could still make _ special case, make it work like Any pattern. |
06:54 | <hax (HE Shi-Jun)> | All of this shows that we made a mistake in the design of using |
06:54 | <Jack Works> | for pattern mathcing currently the following works:
|
06:56 | <hax (HE Shi-Jun)> | how when has 'x' work for multiple property? |
06:56 | <Jack Works> |
|
06:56 | <nicolo-ribaudo> | What mistake? using ID = ... instead of something else (example: using { expression } ) |
06:57 | <hax (HE Shi-Jun)> |
|
06:57 | <Jack Works> | or
|
06:58 | <hax (HE Shi-Jun)> | Using |
06:58 | <Jack Works> | note { let x } and has 'x' are both additional feature and may not exist in the final version. see https://tc39.es/proposal-pattern-matching/ for details |
06:59 | <Jack Works> |
|
06:59 | <hax (HE Shi-Jun)> | Consider pattern match is new syntax, we always can make when { x: _ } work, (at least work if there is no _ binding exist?) |
06:59 | <littledan> | This proposal is good. I hope we do it. |
07:00 | <littledan> | I wonder how browsers feel about this, if they want it to be a desugaring |
07:00 | <ljharb> | Consider pattern match is new syntax, we always can make |
07:00 | <Jack Works> | Consider pattern match is new syntax, we always can make |
07:01 | <hax (HE Shi-Jun)> | it would be very bad if it sometimes was a binding and sometimes was a discard _ is special case. (it's already special in practice) |
07:01 | <ljharb> | the contention on the discard bindings proposal is that some think it is, and some think it's not. i think it's not. some people definitely treat it as if it's special, is all. |
07:01 | <Justin Ridgewell> | Ron mentioned that when { x: y } => ⌠means that itâs matching that the object has the structure {x} and x âs current value is equal to y . Rust doesnât have that, it only matches structure and extracts values, you use an additional when { x } if (x === y) => ⌠to specify an exact value. |
07:02 | <danielrosenwasser> | Ron mentioned that FWIW https://x.com/pcwalton/status/1359970388839550976 |
07:02 | <littledan> | I just havenât seen the _otherString pattern in enough cases where it felt like something someone actually wanted to write |
07:02 | <rbuckton> | If JS didn't have two popular libraries regularly aliased as _ , I'd say sure let's special case it. but unfortunately, we do. |
07:02 | <shu> | I wonder how browsers feel about this, if they want it to be a desugaring |
07:02 | <shu> | personally i think it is not necessary at all but i won't fight against it |
07:03 | <shu> | happy to take devs at their word here |
07:03 | <yulia> | yeah this looks pretty minor to me as well |
07:03 | <hax (HE Shi-Jun)> | If JS didn't have two popular libraries regularly aliased as _ as the alias in recent years I guess? |
07:03 | <littledan> | for me personally the complexity is pretty low unless i'm missing the parser work needed to resolve ambiguities |
07:03 | <ljharb> | but I think most people do not use |
07:03 | <shu> | it's always a cost/benefit tradeoff |
07:03 | <shu> | like if there's no cost ot make devs happier, why wouldn't we? |
07:03 | <Justin Ridgewell> |
|
07:03 | <rbuckton> | Regarding Rust pattern matching. Rust knows statically whether a RHS in a pattern is an existing binding or a new binding, JS does not. Any code could introduce a new global that could change the meaning of something like match (value) { { x: x, y: y }: ... } |
07:04 | <littledan> | Why would it make devs happier if they are all using tools? |
07:04 | <keith_miller> | Well I hate devs personally :P |
07:04 | <shu> | well i do also respect the haters |
07:04 | <rbuckton> | Because JS cannot determine this statically, the pattern matching proposal says an identifier in a pattern is always a reference. If you intend it to be a declaration, you must use let /const /var to declare it. |
07:05 | <Justin Ridgewell> | Regarding Rust pattern matching. Rust knows statically whether a RHS in a pattern is an existing binding or a new binding, JS does not. Any code could introduce a new global that could change the meaning of something like |
07:05 | <rbuckton> | So you would write
|
07:05 | <hax (HE Shi-Jun)> | tons of people still do for underscore/lodash, at least _ or $ in no module era (before commonjs), it seems become less and less after we adopt modules, especially esm. |
07:06 | <danielrosenwasser> | The context is that you have a choice in pattern matching on whether a bare identifier denotes a new binding, or an existing binding to be checked against |
07:06 | <nicolo-ribaudo> | Regarding Rust pattern matching. Rust knows statically whether a RHS in a pattern is an existing binding or a new binding, JS does not. Any code could introduce a new global that could change the meaning of something like In rust it's just syntax-based, right? i.e. in this case you are introducing a new binding
|
07:06 | <rbuckton> | Because your patten matching means something different than Rust's. |
07:06 | <ljharb> | Not sure about it. I think people use |
07:07 | <Justin Ridgewell> |
x , you are never matching a value y === Some(x) |
07:08 | <Justin Ridgewell> | To match a value, you use an if check on the case |
07:08 | <rbuckton> |
Some(x): may seem obvious, but what about just { x: Number } . Should I be declaring a new variable named Number or referencing the Number constructor? |
07:08 | <Ashley Claymore> | yeah this looks pretty minor to me as well |
07:08 | <hax (HE Shi-Jun)> | 123K results on github alone https://github.com/search?q=%22import+*+as+_+from+%27lodash%27%22&type=code |
07:08 | <ljharb> | lol, careful github doesn't autoban you :-p |
07:09 | <rbuckton> | would there be any (tiny) advantage to engines, to immediately know the binding is a discard as opposed to discovering that only once the parse finished? Potentially keeping the set of names to track smaller |
07:09 | <yulia> | would there be any (tiny) advantage to engines, to immediately know the binding is a discard as opposed to discovering that only once the parse finished? Potentially keeping the set of names to track smaller |
07:09 | <yulia> | yep (we do anyway) |
07:10 | <rbuckton> | So yes, there is probably a tiny benefit to implementations since they don't need to hold onto a local for those variables. |
07:10 | <rbuckton> | The spec text also skips adding a binding. |
07:10 | <Ashley Claymore> | I was thinking 'during the parse', rather than 'before the parse' |
07:11 | <Justin Ridgewell> | Can anyone on the call hear the room? |
07:11 | <yulia> | thinking |
07:11 | <danielrosenwasser> | For a using you still need to basically keep the "discarded" value around until the end of the scope, so even if it's not identifiable by a variable name, some work needs to happen. |
07:12 | <danielrosenwasser> | (right?) |
07:12 | <nicolo-ribaudo> | shu It's what the user reads in the callback of the event listener |
07:12 | <rbuckton> | For a using , there are two memory locations that hold the value. One is in the environment record for later disposal, the other is in the variable binding itself. |
07:12 | <yulia> | you would still do the whole parse before constructing the necessary stuff for the script's representation. so this wouldn't be a benefit during parse i think... i don't recall the details of the proposal right now -- if a const binding is void is that name disallowed in the function? im not sure it would help, that might just be more stuff to track and then throw errors on |
07:13 | <shu> | shu It's what the user reads in the callback of the event listener |
07:13 | <yulia> | you'd still have to do the full parse. but, we could discard it as part of our count of things that are local to the function, thats true |
07:13 | <yulia> | i don't think its a huge improvement |
07:13 | <littledan> | Is there time for a timebox extension? This proposal deserves a bit of discussion |
07:14 | <Chris de Almeida> | yes |
07:14 | <Michael Ficarra> | yeah it should've been given a bigger timebox to begin with |
07:14 | <nicolo-ribaudo> |
|
07:14 | <nicolo-ribaudo> | ^ example of the two contexts |
07:15 | <nicolo-ribaudo> | If the dispatch happens from user interaction, than that's null |
07:15 | <nicolo-ribaudo> | If it's from JS code, there is something |
07:15 | <shu> | uh i forget the signature for run() |
07:16 | <Justin Ridgewell> | uh i forget the signature for run() |
07:18 | <yulia> | hello everyone, I am your ersatz chair for the next 5 min |
07:21 | <yulia> | chair relinquished |
07:21 | <jkup> | you had a good run |
07:31 | <nicolo-ribaudo> | For whoever can speak to Mark: I can come to TG3 next week if we don't get to your TCQ topic |
07:32 | <Aki> | ljharb: âď¸ |
07:34 | <jkup> | Did the call drop remotely? |
07:35 | <nicolo-ribaudo> | It was you in the room having problems |
07:35 | <nicolo-ribaudo> | I could hear Mark well |
07:47 | <Aki> | while we're between agenda items: i'm looking for an example of a small proposal focussed on developer ergonomics that went through the stage process pretty smoothly in the past few years |
07:48 | <rkirsling> | I think Promise.try flew through pretty quick |
07:48 | <Rob Palmer> | Promise.withResolvers |
07:49 | <nicolo-ribaudo> | I think Promise.try flew through pretty quick |
07:49 | <rkirsling> | oops |
07:50 | <jkup> | 8 years according to the champion |
07:50 | <rkirsling> | totally missed that part somehow lol |
07:50 | <nicolo-ribaudo> | To be fair it has been at stage 1 for 7 of those 8 years |
07:51 | <ljharb> | stage 2 to 4 was indeed smooth |
07:51 | <ljharb> | 1 to 2 was a beast tho |
07:55 | <rkirsling> | "gently unsure" is such a great phrasing |
08:00 | <shu> | in general, for API features that are purely motivated by convenience, i'd like us to take a bigger scope view and do some prioritization |
08:00 | <shu> | michael has followed a program of 'make iterators more helpful', which i personally agree is well motivated |
08:01 | <shu> | but i do regularly hear the deficiency of the JS stdlib |
08:02 | <shu> | to take a personal pet peeve: we don't have some pretty basic data structures, like Queue, and people are using arrays to poorly emulate. how does something like that weigh against 'make iterators even more helpful' |
08:02 | <yulia> | yeah, thats a good question |
08:03 | <rkirsling> | is that a true statement? I have always viewed the push/pop/shift/unshift methods to imply that arrays simply are stacks or queues or whatever |
08:04 | <ljharb> | arrays are sadly queues, and stacks, and lists, all at once |
08:04 | <shu> | there are crimes being done in the engine to support the expected algorithmic complexity of queue vs stack vs random-access arrays |
08:04 | <shu> | that's what i meant by "poorly emulate" above |
08:04 | <Michael Ficarra> | also MultiMaps! |
08:05 | <shu> | yes, you can use them as such, but we'd also like have data structures fit for purpose |
08:05 | <Michael Ficarra> | please someone give us MultiMaps |
08:05 | <shu> | it might be a bit late |
08:05 | <rkirsling> | relative to which it would seem needlessly Java-like to demand a Queue or Stack class... but then that could also have been an argument against Map (wrt Object), so |
08:05 | <nicolo-ribaudo> | please someone give us MultiMaps |
08:05 | <rkirsling> | maybe the times have simply changed on me |
08:06 | <nicolo-ribaudo> | Oh no it's something else |
08:08 | <nicolo-ribaudo> | I was distracted |
08:08 | <nicolo-ribaudo> | What's happening now? Are done? |
08:08 | <Chengzhong Wu> | Restricting subclassing support in built-in methods: Telemetry Results (Firefox) Update |
08:08 | <shu> | no, we're doing yulia's update on killing species |
08:09 | <Justin Ridgewell> | Yulia is presenting subclassing |
08:09 | <shu> | i should've named the proposal Extinction |
08:09 | <nicolo-ribaudo> | Oh ok thanks to who spoke |
08:09 | <Chengzhong Wu> | 20min |
08:13 | <rbuckton> | I use Symbol.species for Array subclasses when I don't want .map /.filter to produce an instance of the subclass because the constructor parameters differ. |
08:14 | <rbuckton> | Without it I have to override map, filter, slice, et al and provide my own implementation. |
08:14 | <shu> | that seems better |
08:14 | <rbuckton> | Not really. |
08:15 | <Ashley Claymore> | if we hadn't of done Symbol.species, wouldn't you have gotten your desired behaviour by default? |
08:16 | <rbuckton> | It's not that I need Symbol.species . It's that I need some way to tell the superclass to just produce Array and not my subclass. |
08:17 | <rbuckton> | Yes, if we didn't have symbol.species and the default behavior was not to try to produce an instance from the current constructor, that would have been acceptable. |
08:18 | <Ashley Claymore> | This is what we do in the new Array methods |
08:18 | <littledan> | XRegExp was a big source of type 4 stuff |
08:18 | <rbuckton> | But if you unship Symbol.species you need to choose whether to only return Array instances or to only return this.constructor instances. The question is who are you breaking by choosing one or the other. |
08:19 | <nicolo-ribaudo> | I feel that "Yeah" very hard |
08:19 | <Ashley Claymore> |
|
08:21 | <littledan> | But if you unship Symbol.species you need to choose whether to only return |
08:21 | <rbuckton> | Essentially, I only use Symbol.species to work around the existence of Symbol.species. |
08:22 | <nicolo-ribaudo> | Can we use AI to filter those cases |
08:22 | <nicolo-ribaudo> | Google is already shipping it in the browser |
08:22 | <nicolo-ribaudo> | It can run in the background and check all the loaded pages :) |
08:22 | <rbuckton> | I have no intuition as to how many people are subclassing Array and it actually matters that .map() et al produce a subclass. These implementations wouldn't be overriding Symbol.species , just using the default behavior. |
08:27 | <Justin Ridgewell> | Yah, Type II Array uses are probably genuine |
08:27 | <Justin Ridgewell> | Itâs just too simple for a web dev to have written |
08:29 | <rbuckton> | Historically we've had two opposing positions on subclassing and overriding methods:
|
08:30 | <rbuckton> | For example, (1) was the approach considered for things like customizing keying for Map /Set . |
08:31 | <rbuckton> | 1 and 2 aren't polar opposites, but they do cross purposes wrt Symbol.species and how/when to handle subclass construction for results. |
08:33 | <rbuckton> | A third approach is wrapping, but you cant wrap an Array due to its exotic nature. |
08:34 | <rbuckton> | (at least, not without a Proxy , which is hard to get right and slow) |
08:50 | <hax (HE Shi-Jun)> | Symbol.species provide a hook which just like protected member in OOP. Compare to other protocol I don't think it's inevitable evil. My question is why it's a static property? If it's a instance property, would it be better for the engines? |
09:55 | <Anthony Bullard> | I think the thing missed in this discussion is that in languages that do a ton of this, and where itâs fast (zero cost-ish or better) the extraction requires no function call or hidden user code. Itâs literally the same lookups and comparisons you can see in the patterns and possibly some branch caching. If we got rid of Extractors with custom user code, 90% of concerns over hidden perf costs go away |
11:56 | <Duncan MacGregor> | Did the "Next meeting host and logistics" agenda item get cut, or was it simply not minuted? I don't see it in the day 1 notes. |
23:12 | <Michael Ficarra> | Did the "Next meeting host and logistics" agenda item get cut, or was it simply not minuted? I don't see it in the day 1 notes. |