ECMAScript 2017: the final feature set
2ality.com
2ality.com
Collections in js are modelled with Arrays, (Weak)Maps, (Weak)Sets, Iterators, iterables/iterators, strings, promises, Nodelists, typed arrays, objects (where structs would be used in other languages), generators, collections provided by third party libraries (e.g. immutable structures)
There is no convenient set of methods that work on all of these, and no protocol that you could use in your thirdparty library to behave in a consistent and expected way.
The closest we have is iterables, but you can do very little with an iterable beyond iterating it. No map, no filter, no flatmap, no reduce. You can create a new array out of it and then use the array methods (which don't exist on any other collection), but that's pretty dumb too.
"We'll let libraries decide" is the usual cry, but it's impossible to write functions that will appear only on iterables or iterators, since they have no common prototype other than Object.
Ideally the language itself would provide a small, coherent protocol that all collection and collection-like things could implement, and then all the good stuff could be built on top.
Languages like clojure do a good job of this.
ES6 generators pretty much solve this, especially once you learn "yield*"
(Compare with C# where a laundry list of higher order LINQ operators are provided out of the box as extensions to IEnumerable. Or Python's 2.x itertools modules, many of which have filtered into the top level of the standard library in Python 3.)
During my Java days, I saw countless broken attempts at writing parallel code (typically only saved by the Java VM not exploiting all possibilities the spec allows for, such as only updating shared global state at the end of a synchronized block).
Along came NodeJS and proved to us lost java souls, that with non-blocking I/O, you don't need hundreds of threads to make performant code. In fact, one thread is enough, also for driving complex UI.
Now we're given wonderful new Atomics and SharedBuffer, I bet there will be an underlying expectation that to "keep up" you better start driving complex UI in multiple web workers, because, performance.
But the complexity of coding parallel stuff hasn't gone away. Atomics and Run To Completion functions isn't simple.
I would not be surprised if I'm two years from now am debugging broken attempts at writing parallel code in something like react-parallel.
I don't think that web workers and the shared arraybuffers will make that worse. It's a tiny loophole that let's one exploit parallelism for a number of very specific use cases. For the average UI it's far too complex to use, since it does also not directly allow sharing objects but only byte arrays, which means users would need to care for serialization. So the possibility of misuse is low.
For a specific set of applications (audio/video processing stuff, game engines, thinks that are cross compiled from C++) it could be an important building block that allows to exploit parallelism there. And I think in these use-cases the implementors would more likely know what they are doing when the shuffle bytes around.
The mindset is that of the Extensible Web: https://extensiblewebmanifesto.org/
Basically, a lot of work is currently being done on WebAssembly and wasm.js. This means that languages will be compiled for browsers, and some of those will need/want parallelism. The question is: what do they need for that?
Shared buffers allow for constructs to be built on top to explore what primitives are needed for parallelism for compiler targets.
> In fact, one thread is enough, also for driving complex UI.
Swing and JavaFX are single threaded, and very capable of driving complex UIs. I fail to see how you needed to switch to nodejs (a backend technology) to find this.
> better start driving complex UI in multiple web workers, because, performance.
UIs have never been parallel. One explanation is the complexity of synchronizing the flow of events coming from the OS (ie input) and to the OS (ie drawing). More on that here [1]
[1] https://community.oracle.com/blogs/kgh/2004/10/19/multithrea...
WPF can have multi-threaded UIs, but it's usually not worth the headache. Although I think every control is bound to the Dispatcher of its containing window, so you can only have one thread per window instead of dividing it finer (not that it matters much, the usual rules of doing nothing computation-intensive on the UI thread still apply).
Go does that yet still need mutexes, has race conditions and memory corruption.
Didn't have a problem since.
The asynchronous single-thread event loop of Nodejs is helpful for offloading IO-bound tasks but doesn't solve cpu-bound workloads.
Therefore, if a programmer wants to develop heavy cpu computations in parallel (rendering, transcoding, image/speech analysis, etc), the "absence of threads" in Nodejs is not relevant to solving those problems. There are many workloads that perform better in a shared-memory multi-thread execution model rather than shared-nothing multi-process (web workers) model.
However, that dichotomy doesn't necessarily justify adding shared-memory threads to Javascipt -- it just changes the wording of the question to a higher-level question: Should the Javascript language+runtime evolve to solve heavy cpu-bound workloads?
Apparently, enough of the Javscript community said "yes" such that it's been added to ES2017.
That stands true. No need to use Workers for IO. We won't suddenly have to use it, because it does not solve a problem for most of us (like promises did, for example).
> start driving complex UI in multiple web workers
I would guess that for 99% of UIs, it would be total overkill to use Workers (you could still offload e.g. AI, in a game).
In general, the push comes from WebGL and similar heavy stuff.
> something like react-parallel
I definitely can see it, especially with redux. Just for the sake of it, someone somewhere will try it.
well, that's certainly one way to avoid another `leftPad` mess :)
That is, if you had the strings "a" and "é" (where the latter is "e\u0301") padded "equally" to length 3, leftpad would pad them approximately thusly:
__a
_é
> leftpad('e\u0301', 3, '_');
<- "_é"Very few languages that I know have deep cloning outside of some sort of serialization hack anyway (C#'s deep cloning is a reuse of/leftover from binary marshalling), so this is roughly par for the course, so far as I'm aware.
Relatively short, but IMO not relatively performant. All the JSON encoding/decoding takes its toll.
Obviously YMMV, and your performance needs likely differ from my own.
(Personally, at this point I try to use immutability [with ImmutableJS or friends] over deep cloning, but sometimes a deep clone is still handy.)
With the language moving this slow compared to faster releasing languages like Python, Elixir, and Go, I wonder if Node.js will start to see a decline in hype since the language hasn't improved much in the last 2 years. What do you guys think?
I'm curious as to what is happening with SIMD. That has been at stage 3 for a long time.
ES2018 is likely to be a bigger revision for classes. I hope we'll see class properties, private state and decorators, and maybe BigInts.
Which makes sense. It's not a perf critical feature, so transpiling is the smart move.
It’s not exactly surprising. ES6 came out almost 6 years after ES5, so there was quite a few changes then. The yearly release cycle was always going to mean fewer features being standardised each release.
While I do follow from a distance some of the work TC39 does, I can only assume that most people involved have realised that having an orderly process for feature proposals - and not trying to rush heaps of features into a single release - is a much better way to do things.
> With the language moving this slow compared to faster releasing languages like Python, Elixir, and Go
Python, Elixir and Go have the advantage that they have one main/reference implementation and can break backwards compatibility whenever they want (although that hasn’t gone brilliantly for Python) by just incrementing a version number. ECMAScript runtimes have to be able to run programs that were written almost two decades ago - backwards compatibility can’t be broken - and you have several major implementations (V8, Spidermonkey, etc.) to deal with.
The tail call feature from ES6 is already being revisited because it caused problems [0].
> I wonder if Node.js will start to see a decline in hype since the language hasn't improved much in the last 2 years.
Tools like Babel mean that people who really want to use new or experimental language features can do so. There are dozens of language features in the proposals pipeline [1] and many (if not a majority) can be used via a compiler like Babel or via a polyfill.
Node.js also has the advantages of having it’s own 'standard library’ and an enormous package ecosystem to use. I think it will be fine.
[0] https://github.com/tc39/proposal-ptc-syntax [1] https://github.com/tc39/proposals
Proper tail calls being in the spec don't cause problems. Safari shipped with them a while ago. Chrome/node has them behind a flag. Google wants them to be explicit and everyone's bikeshedding about which bloated syntax is the correct one (or if it should even have its own syntax).
The actual debugging issues they talk about are non-issues in my book. Catering to new devs who don't understand tail calls is stupid (by that metric, we should get rid of a lot of other things too). We don't need stack traces for tail calls that loop (just like we don't need them in a for loop). A shadow stack works just fine for CPS (continuous passing systems) and is still better than the debugging tools we have for stuff executing across the event loop (aka nothing worth mentioning).