Live data from Hacker News

Go-like channels in 10 lines of JavaScript

pedrocattori.dev

51–60 of 65 posts

Re: Go-like channels in 10 lines of JavaScript

#51
post #11

generator functions exist, which is not even needed in this case, you could just pass a promise as an argument

To be fair, my first thought was that generators solve this roughly with the same (JS-equivalent) semantics. But my second thought was that bidirectional JS generators are painful to write and use. They’re objectively better (particularly because they’re not inherently infectious when they yield), but they’re also unergonomic as heck.

Re: Go-like channels in 10 lines of JavaScript

#52
post #6

But there is no concurrency in Javascript! So even after this exercise, the running function still has to finish before the next can start. This will only create actual concurrency when each of the actors are themselves doing pretty IO heavy things where they wait for external processes to finish. Otherwise, if you actually have compute heavy processes that should run in parallel you should use the node.js cluster pa…

[deleted]

Re: Go-like channels in 10 lines of JavaScript

#53
post #9

Earlier quoted context omitted.

I actually think async/await is a terrible primitive, and if you’re on Java, the approach of Project Loom is vastly superior (i.e. threads can be cheap so everything can just be synchronous again). I’ve no problem with library-level concepts like promises and futures but it feels very short sighted to put it into an actual language, it’s just noise.

Why don't you like async/await? 8 years ago I wrote a npm package that turned code that looks like this: tcp.send("syn", function(syn) { console.log("received", syn); tcp.send("syn-ack", function(synack) { console.log("received", synack); tcp.send("ack", function(ack) { console.log("received", ack); }); }); }); into this: seq([tcp, console], function(tcp, console) { var syn = {}; var synack = {}; var ack = {}; tcp.se…

Sounds like we’re agreeing - nobody _wants_ to write async code cos it’s terrible. You didn’t quite perfect the syntax above but I’m not denying it’s possible - Clojure treats async as a library, not a fundamental language feature, for example. And now with Loom the implementation is even simpler. People want to write synchronous code that can run in parallel without having to do something weird. History will hopefully prove that this is best solved as an implementation detail, not as part of a language’s semantics.

Re: Go-like channels in 10 lines of JavaScript

#54

This needs a comparison with streams, as opposed to promises. Streams are what you would use to achieve this in Node.js land. https://nodejs.org/api/stream.html

Well, the context is Node.js, and I would definitely use promises over streams for what’s described in the article (albeit more directly). Node streams are complicated with a lot of historical baggage, and massive overkill for waiting on a single value produced by another operation.

The point was that it's not a single value, it's a stream of values (e.g the compileServer can start working with partial results of the compileBrowser function). Of course if it was a single value, promises are fine. A simpler and more modern alternative would be async iterators/generators[0].

[0] https://blog.logrocket.com/comparing-the-stream-api-and-asyn...

Re: Go-like channels in 10 lines of JavaScript

#56

Earlier quoted context omitted.

Or use a language that supports multi threading in some sensible manner..

You’re asking for low-level features. JS is a high-level language.

I’m just saying if you want parallelism then don’t write things in JavaScript

Re: Go-like channels in 10 lines of JavaScript

#57

Earlier quoted context omitted.

Well, the context is Node.js, and I would definitely use promises over streams for what’s described in the article (albeit more directly). Node streams are complicated with a lot of historical baggage, and massive overkill for waiting on a single value produced by another operation.

The point was that it's not a single value, it's a stream of values (e.g the compileServer can start working with partial results of the compileBrowser function). Of course if it was a single value, promises are fine. A simpler and more modern alternative would be async iterators/generators[0]. [0] https://blog.logrocket.com/comparing-the-stream-api-and-asyn...

> The point was that it's not a single value, it's a stream of values

But it wasn’t. Despite the author calling it a channel, it only supports one value.

Re: Go-like channels in 10 lines of JavaScript

#58

It's a bit out of fashion, but same thing can be achieved without any extra code using a built-in EventEmitter: let channel = new EventEmitter() await Promise.all([ compile.browser(channel), compile.server(channel) ]) // in compile.browser channel.emit("manifest", assetsManifest) // in compile.server channel.once("manifest", (assetsManifest) => ... ) A new emitter is used each time, so the end result is the same. Cur…

EventEmitter doesn’t hold on to its values, so if the `channel.once` listener doesn’t get attached before `emit` is called, the value will be missed. Also, in order to wait on an event, you usually end up with a promise anyway (so `await` can be used).

[deleted]

Re: Go-like channels in 10 lines of JavaScript

#59
post #31

Earlier quoted context omitted.

Is that concurrency? The CPU is not switching between tasks; rather, it's scheduling 2 callbacks to fire after a 3000ms delay. If you could perform 2 tasks (e.g. console.log(Array(1e8).fill(0).map((a, i) => i)), and have both run to completion without a significant delay between the two tasks, that'd be impressively concurrent.

Concurrency is not parallelism: - Concurrency is making overlapping progress on two or more tasks. - Parallelism is making simultaneous progress on two or more tasks. Concurrent tasks can run in parallel, but they can also run not in parallel and still make overlapping progress by either cooperative or preemptive scheduling. You can imagine that in some larger tasks you have these 3 second sleeps, but all tasks are a…

There is a great talk by Rob Pike: Concurrency is not Parallelism - https://www.youtube.com/watch?v=oV9rvDllKEg&t=23s

Re: Go-like channels in 10 lines of JavaScript

#60

Earlier quoted context omitted.

No. All the JS code is still executing serially in the same event queue. This is a good thing, lean into the guarantees it provides.

Sorry, I think you’re misunderstanding. Highly concurrent code need not execute in parallel. Concurrency enables parallelism; concurrency does NOT mandate parallelism. On top of that, it actually is possible in JavaScript environments like Node.js to write code that can, in fact, run in parallel.

But those parallel executions are running their own event queues.
Post reply on HN