I feel like Erlang is a functional language that's honest about systems, not just a program. You are almost required to write distributed apps with Erlang, just because it's not weird to spin up thousands of Erlang processes, and you don't have any real way of knowing the order they're going to run so you have to build your applications around async messaging.
It makes me a little sad that Erlang/Elixir is kind of the only platform that does this though...
My experience with elixir, as a scrub who spends every day at work writing javascript, is pretty in line with that. The language forces you to work that way, and you spend half your time just architecting your supervision tree. But the language itself is so easy to write business logic in that it takes half as long as it would in another language. So it works out to the same total time investment but the return is so much higher cause your program is better and more predictable and has scaling for free.
>It makes me a little sad that Erlang/Elixir is kind of the only platform that does this though...
It's not. These are called green threads and under the hood it's not really threads. It's literally the same thing as async await in python and nodejs.
It's just different perspectives on the same concept of concurrency. Go and Erlang implicitly have calls to concurrency, while nodejs it's implicit.
No, it’s not literally the same thing. I’m afraid you greatly underestimate and fundamentally misunderstand Erlang processes by making such comparison.
I’m not underestimating Erlang processes. I’m saying the distinction you’re drawing is largely semantic and policy-level, not a fundamentally different concurrency mechanism.
Erlang processes, goroutines, and async tasks are all cooperatively scheduled user-space execution units multiplexed over OS threads. That is the same underlying concurrency primitive. There is no new physics here.
Erlang’s real contribution is that it forbids shared memory, bakes message passing, supervision, and restart semantics into the runtime, and forces a particular design discipline. That’s a design rule, not a different execution model.
You can approximate Erlang’s semantics on top of async/await or goroutines; you cannot approximate preemptive shared-memory threads on top of Erlang. That asymmetry tells you where the real difference lies.
Treating policy and guarantees as if they were a different kind of concurrency entirely is what causes people to mystify Erlang instead of understanding why its constraints work.
It sounds to me like an exercise in wordplay within very broad definitions. My initial reaction was towards the claim "It's literally the same thing as async await in python and nodejs" which is only true in such case.
I think you’re missing my point. Even if they were using “real” thread then it then Erlang’s messaging semantics would remain largely unchanged.
Also, it’s not the same thing as async nodejs. Node.js is a fully cooperative system, something CPU intensive can hog the thread and starve the other tasks. Erlang processes are preemptive; every process gets N reductions and then it is parked and the next process can make progress. They’re closer to OS processes than goroutines.
It makes me a little sad that Erlang/Elixir is kind of the only platform that does this though...