When you combine those together you end up with a situation where "normal" js code not from a library can't be trusted on the front end because it won't work for x% of your users, and offers a clumsy API on the backend that you'd prefer be wrapped in a helper. Developers learnt that they should reach for a library to e.g. deal with localstorage (because on Safari in private mode the built-in calls throw an error instead of recording your data and discarding it after the tab closes) or make a HTTP request (because node doesn't support fetch yet and you don't want to use the complicated streams and callbacks API from the standard lib) and they propelled that culture forward until everyone was doing it.
We’ve been blessed in recent years that either languages are fully open source and come with a reference implementation, or a standards body governs the implementation detail. Sometimes even both.
Whereas JavaScript is really more a group of languages, each with their own implementation quirks.
ECMA was intended to bring some sanity to all of this. And it’s definitely better than it was in the JScript days of IE vs Netscape. But there isn’t anything (that I’m aware of) that defines What should be a part of the JavaScript standard library.
Wouldn’t it be great if there were a libc in the JS world. Something portable and standardised.
I mean, it’s not necessarily “in the JS world”, but WASM is basically that.
You may be thinking of WASI?
This feels like a bit of a strawman, since sorting is already in the standard library and there aren’t in fact popular sorting packages for each framework (that would in fact be ridiculous).
If you want to start a real debate though, bring up date/time pickers.
There are multiple date picker, time picker and datetime picker packages for each framework, and there are debates with good points on all sides about whether the browser-provided pickers are sufficient, or whether this is an area where a level of customization is needed and what that level is keeps changing as people discover new ways of designing date/time pickers and new use cases arise that require different tradeoffs. It’s both really frustrating but also kind of understandable.
const idx = [1,2] const m = new Map m.set(idx,"hi!") console.log(m.get(idx)) // outputs "hi!"
console.log(m.get([1,2]) // outputs undefined
That last line has created a new array object, and Map is made to be fast so checks equality by reference. Ah, which is what you to be able to change. I guess you would want to pass a new map a comparator function, so that it does a deep equal. That would be faster than what you would have to do now:
const idx2 = String([1,2]) m.set(idx2, "yo") console.log(m.get(idx2)) // yo console.log(m.get(String([1,2])) // yo
Stringification is a very crude hack, and it doesn't even work in all cases - e.g. not if a part of your key still needs to be compared by reference. Say, it's a tuple of two object references, describing the association between those two objects.
Either way, the point is that this is really basic stuff that has been around in mainstream PLs for literally many decades now (you could do this in Smalltalk in 1980!).
Of course, Records and Tuples would greatly simplify the process.
What I meant was that it's possible to emulate a custom key comparison predicate.
You just have to have a function that returns value for each input that behaves the way you want under strict equality comparison.
Implementing an `equals` function that returns a boolean is more convenient, sure.
Serializing (for plain objects with only JSON-serializable values that would be JSON.stringify) to strings or other primitives would of course be possible with object keys, too. But that's probably what you want for "record"-like objects, right?
And if you want better performance or compare non-primitive values, you'd have to do something more complex, that's what I meant by the lookup table.
But I imagine if you deep-compare large Record objects a lot, the performance wouldn't be any better, because the engine still has to do a deep comparison.
If I am not mistaken, Records/Tuples are in fact strictly limited to this case:
https://github.com/tc39/proposal-record-tuple#jsonstringify
So basically there is no difference to having a function serialize() that just stringifies your plain object, maybe with a caching layer in between (WeakMap?)
OK, thinking about it, the proposal really would help to avoid footgun code where performance optimizations are lacking, and too many deep comparisons or too many serializations are performed.
Right. For example, to sort a list of numbers:
[5, 14, 1, 2].sort()
Works great! No, wait, that's obviously wrong. Uh, [5, 14, 1, 2].sort((a, b) => a - b)Safari (iOS and MacOS) still doesn't have full support for the date time picker, which is why there are so many alternatives.
That said, you can still have a core set of “blessed” packages that serve the common needs.
Rust has a good standard library and also a large community of libraries. Sometimes those community libraries get promoted to std because they're strictly better. Sometimes the std version of hashmap is slow because std insists on using a crytographically secure hash when 99.99% of use cases would be better served with a less secure but faster hashing algorithm.
Like many things in life the ideal scenario is a benevolent dictator that only makes good choices. In practice the best way to get something good is to allow for multiple choices.
<insert parable of pottery class graded on quality vs quantity>
Meanwhile, the horrible C++ and Python API designs at least offer the needed functionality, even if the code looks ugly.
You see it in Go, Python, .NET, etc.
While I agree here, you also have to remember that additions to the JavaScript standard also increase the amount of time / effort for new browsers to enter the space.
The JavaScript standard (the web APIs, mainly) are already very complex, with Web Workers, Push Notifications, Media Streams, etc. that additions to it should be made cautiously -- once an API is implemented, it's there forever, so the bar for quality is much greater than that of some NPM library.
Yes it should be done carefully. There are also plenty of examples of how this can be done well, done by experienced engineers. For example, the Dart starndard library (https://dart.dev/libraries - core [1], collection [2] and async [3] in particular) is a very good model that would fit JS fairly well too (with some tweaks and removals)
[1]: https://api.dart.dev/stable/3.2.4/dart-core/dart-core-librar...
[2]: https://api.dart.dev/stable/3.2.4/dart-collection/dart-colle...
[3]: https://api.dart.dev/stable/3.2.4/dart-async/dart-async-libr...
It's still a nonzero amount of complexity. I see a lot of "v8 is really hard to compete with" comments on here so this feels very pertinent to mention. You can't have it both ways.
> Yes it should be done carefully. There are also plenty of examples of how this can be done well, done by experienced engineers. For example, the Dart starndard library (https://dart.dev/libraries - core [1], collection [2] and async [3] in particular) is a very good model that would fit JS fairly well too (with some tweaks and removals) > > [1]: https://api.dart.dev/stable/3.2.4/dart-core/dart-core-librar...
This one, at least, looks somewhat inspired by JavaScript.
That sounds great, but I'm doubtful of the simplicity behind this approach.
If my understanding is correct, v8 has transitioned to C++[0] and Torque[1] code to implement the standard library, as opposed to running hard-coded JavaScript on setting up a new context.
I suspect this decision was made as a performance optimization, as there would obviously be a non-zero cost to parsing arbitrary JavaScript. Therefore, I doubt a JavaScript-based standard library would be an acceptable solution here.
[0]: https://github.com/v8/v8/tree/main/src/runtime [1]: https://v8.dev/docs/torque-builtins -- As I understand it, Torque compiles to C++ at compile-time, which is then linked and compiled into the rest of v8[2]. [2]: https://github.com/v8/v8/blob/main/tools/torque/format-torqu...
(Or are they still trying to make Servo viable?)
There's plenty of competition, even if the current projects are in a beta (or even alpha) state. Consider the LadyBird browser developed by SerenityOS, or Servo.
Go has a big standard library too and it's mostly very well designed, useful and avoids fragmentation.
I think a similar thing happened with compiler warnings and C/C++. The language is error prone so people want warnings but a lot of the warnings don't have good solutions (e.g. signedness mismatches) so people tend to ignore them. Also they aren't easy to control, e.g. from third party dependencies.
So some people got the idea that warnings are fundamentally wrong and e.g. Go doesn't have them. But my experience of Rust warnings is that they are totally fine if done right.