Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'd like to know why erlang doesn't count?

There are plenty of reasons to use JS, like "I already know it" if you're a front-end dev, "It's our only option on the client-side and using the same language everywhere is a good idea", or "V8 is heavily optimized so I can not care about performance and usually my code will run fast enough."

Actually that last one is nice. If you don't do anything too stupid, and break up work into lots of little pieces that are called exactly when they're needed, and share as little state as possible, your code runs /much/ faster and is much easier to reason about. node.js gives you those last two properties by default.

Perhaps "JS is inordinately popular for how bad of a language it is", and "Only erlang has the same concurrency model" are related. You can write something that runs as fast in another language or environment, but you won't be able to write it nearly as easily.



I'd assume erlang doesn't count cause the way you do concurrency in it is the opposite of you do it in node (a bunch of stateless processes communicating over stateful channels vs a single stateful process with callback spaghetti)


There is no channel in Erlang. Each process has a mailbox. Each process is stateful. Node has only 1 and it works with callbacks as a way to do cooperative scheduling, Erlang has N of them and they work through message passing, using preemptive scheduling.

They have nearly nothing in common.


They're more or less duals: move the functions to the data via closure thunks as callbacks, versus move the data to the function via messages.


You put it much better than I could.


They don't have the same concurrency model.

JS uses callback-based stuff, cooperative scheduling, and has a single process to drive everything.

Erlang has message-passing to mailboxes, preemptive scheduling, and many fully isolated processes.


They look different but what matters is the same.

Cooperative vs. preemptive scheduling is only about whether you trust the coroutines to do the right thing. Erlang cares about recovering from errors so it must be preemptive. Node.js trusts the programmer so it uses a much simpler cooperative scheduler. This does not change the concurrency model though, only the assumptions of the environment.

Erlang is (in my opinion at least) better than node.js, and also has the advantage being able to enforce no-shared-memory between actors, so it automatically distributes erlang processes across all your cpu cores. Node.js requires that you spawn child processes yourself if you wish to take advantage of multiple cores, but ones they're spawned the way you handle concurrency doesn't change.

I don't know about you, but mailboxes and callbacks look pretty close to the same thing to me. In both, your code waits for an event to happen and then reacts to that event, potentially sending off more events. In both, once you do anything that would require blocking, your coroutine lets others run while it's waiting.

The erlang model certainly has more power but they're more similar to each other than they are to anything else. The way you think is the same, although the way you write it might be a little different.


Preemptive scheduling also allows to add some interesting real-time guarantees by knowing some processes will be scheduled when they need to be busy, or to do it based on how much is waiting for them by interrupting others.

For example, an overloaded Erlang node will favour the processes that are being swamped over the other ones in an attempt to try and rebalance things. This is especially efficient during short overload bursts. Cooperative scheduling cannot explicitly do the same, or give any indication of how frequently or how much work you want to let a work unit do.

Regarding mailboxes and continuations through callbacks, not exactly. One difference is that Erlang has selective receives, whereas callbacks will be handled no matter what. This means that in Erlang, I can choose to only care about a subset of the possible events and leave the rest for later, waiting and blocking my execution until I get the right circumstances. In callback-based code, I have to think of all possibilities because callbacks can't block.

This is to say the event matrix of callback-based code will need to consider all options, while Erlang's will only need to handle a restrictive subset of them. Ulf Wiger gave a full talk on it, which is summarized here: http://dm3.github.com/2010/08/01/death-by-accidental-complex...

This also impacts how easy to maintain code, reason about it, model it, etc. You don't have to think the same because you don't have to consider nearly as many possibilities, event interleavings, or worrying about blocking stuff and killing your application (an irresponsive app is as good as dead) because of it.

And I'm not even getting into the need of callback-based code to break everything into continuations.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: