Because outside of Go (and maybe Rust) it will be very difficult to actually do what Elixir does, with the same level of concurrency and fault tolerance, etc, with the same ergonomics.
Ruby/Rails/StimulusReflex does something very similar, but kind of falls over unless you replace ActionCable with AnyCable which is written in Go.
So now, you have to support Go and Ruby runtimes. Some developer who decided that the above was a nightmare to work with, __might__ start a new project in Elixir, to get something that actually does what Elixir does instead of just mimicking it.
I'm not sure I buy this, personally, but I can understand the argument.
It's just as difficult in Go and Rust. BEAM, the Erlang VM that powers Elixir, is not just about lightweight processes. It's also about guarantees that neither Go nor Rust provide. E.g. to do what Elixir does you need robust process supervision trees. You can imitate, but not replicate those in other languages.
I'm in full agreement with you, but I'm not sure you need full robust process supervision trees to mimic what the BEAM does in the context of LiveView on a single machine.
I do want to say, I 100000% times prefer Elixir, it's tooling, ecosystem, web frameworks, easy of scaling vertically and horizontally, etc over Go or any other lang that probably do something analogous to LiveView via what ever concurrency primitives that language/runtime champions; Go with it's Communicating sequential processes(CSP) and Rust with the Ractor lib (https://github.com/slawlor/ractor).
Erlang VM guarantees that [1]
- all processes are isolated. Fatal error in one process will not affect other processes. Crucial: it will not affect the VM.
- If you set up process monitoring, and that process dies for whatever reason the monitor will be notified, with the actual reason. This lets the monitor (the supervising process) decide what to do next: restart, do nothing, stop entirely etc.
- Other relevant things like processes suspended when waiting for messages, or running out of reductions (number of allocated calls and messages) so that other processes can be executed, a bunch optimizations in the VM about CPU caches etc.
So what you have is "kubernetes for processes, inside the VM".
And the reason you don't have supervision for either Go or Rust is simple. Both Go and Rust for some completely asinine reasons decided that an unhandled error should kill the entire running application, with no chance of recovery.
And later they both awkwardly bolted on a half-assed solution to catch panics. That's it. That's the extent of error handling and guarantees in those languages. Of course no one builds supervision trees there.
[1] Of course it's not a 100% guarantee, nothing is, but other languages don't have even that.
Erlang'd documentation used to have a section called "Do not program defensively" [1] This is known as "let it crash" philosophy. Or, better put, that Erlang has auto healing mechanisms [2]
When applied correctly, it significantly reduces the amount of boiler plate code you need to write because you're only concerned with the happy path in most of your code.
[1] A copy is available here: https://docs.jj1bdx.tokyo/Erlang_Programming_Rules.html#HDR1...
[2] Erlang has auto healing mechanisms
Then in the vast majority of cases we wouldn't run kubernetes clusters running docker containers for one-off tasks and single services. Or "serverless functions".
Unfortunately even the otherwise very smart folks of Go and Rust only see "ah, lightweight threads, got you". That's why, for example, you get irrecoverable panics in both languages and awkward attempts to patch over them in later versions.
Meanwhile Armstrong's thesis "Making reliable distributed software in the presence of hardware/software errors" is over thirty years old now.
Should it?
> otherwise very smart folks of Go and Rust
Ahh, everyone else is wrong. Gotcha. RabbitMQ is life(LOL), god save the BEAM!