Joe Armstrong about Elixir, Erlang, FP and OOP
In the past few days, a number of articles have been published on Habré, the general leitmotif of which (especially in the comments) was the confrontation between blunt and pointed people - adherents of the FP against the PLO, although they were called not to argue. Erlang was sometimes discussed, in connection with which I recalled a short post on a topic from Joe Armstrong, one of the creators of this language, written by him at the end of 2018 on the Elixir forum in response to a question about the language paradigm. I think his comment will be interesting.
Joe Armstrong September 12, 2018
All the good things about Elixir (and Erlang) are related to concurrency - just creating independent processes and messaging. And this is exactly the essence of object-oriented programming, as Alan Kay has repeatedly pointed out.
OOP is fully dedicated to objects. Objects respond (or should respond) to messages, and when you want to do something, you send a message to the object, and how it processes it is completely irrelevant. Think of objects as "black boxes", and when you want something from them - just send messages, and they will send you messages in response.
How everything is arranged inside does not matter whether the code inside the black box is functional or imperative - only what exactly it should do is important.
Unfortunately, although the first successful object-oriented language based on this model (Smalltalk) operated on the concepts of "object" and "message", the latter in Smalltalk were not real messages, but only masked synchronous function calls. The same error was repeated in C ++, then in Java, and the main idea of OOP degenerated into a strange paradigm for organizing code into classes and methods.
Erlang and Elixir make it easy to create millions of isolated processes where everything works by sending messages between them. The architecture of the system is determined by the level of parallelism that you want, with its subsequent mapping to the processes directly.
The Elixir web server for 10,000 users is not "one web server with 10,000 users" (as is the case with Apache or Jigsaw and the like), but it is "10,000 web servers per user" - agree, a radical departure from the traditional model.
The fact that a simple functional language was used to describe the Erlang / Elixir process model is almost an accident. It all started with a logical programming system (Prolog), and things like C-node, for example, can be written in any language at all. The really important thing for Elixir (and any other BEAM language) is the ability of their virtual machine to operate with an extremely large number of parallel processes.
For a long time I said that "Erlang is the only real object-oriented language." I guess now I can add to it and Elixir.
For OOP, the basic things are:
- isolation between objects (we have it)
- late binding (we decide what to do only when the process receives a message)
- polymorphism (all objects can respond to a message of the same type, for example, "print-yourself" and any object can know how to do this)
Much less important:
- division into classes and methods
- software model (functional or imperative)
After we divided the system into a large number of small processes communicating with each other, everything else becomes (relatively) easy - each process should be quite simple and be able to do quite a bit, which greatly simplifies programming.
What Erlang (and Elixir) brought to programming was the idea of communications (link - approx. Translator). Initially proposed by Mike Williams, it consists in expanding the possibility of error handling, allowing it to be done outside the boundaries of processes. Having this, we got all the necessary tools for building supervisor trees, etc.
Supervisors, gen_server's and all that jazz are just libraries that hide some details from the user. Simple inside, written using the same tools - parallel processes and the relationships between them.
Erlang was not developed as a functional programming language, but as a tool for creating long-lived fault-tolerant systems.
A central element of fault tolerance is the concept of remote error handling. If the whole system fails, the malfunction must be fixed (compensated) on another machine, since it is already impossible to do it locally - the local computer is not working.
This means that for programming fault-tolerant systems, we need the distribution (of processes) and messaging to be easy-to-use tools, and that is why, in principle, any fault-tolerant architecture will ultimately be similar to Erlang.
The whole point of creating Erlang was to simplify the programming of fault-tolerant systems, a side effect of which was the ease of programming scalable systems.
The difference between Erlang and Elixir and “everyone else” is in the mechanisms for ensuring concurrency and fault tolerance, and we are not talking about monads, syntax, or “purity” of FPs.
Now the question is - do you want to process 10,000 users in one thread, using callbacks to emulate concurrency, or do you still want to create 10,000 parallel processes, each of which is simple and does not need callbacks at all?
Each process waits for the message in which it is interested, then performs calculations and falls asleep in anticipation of the next.
I think the big problem with promoting Erlang / Elixir is that you need to explain how a lot of parallel processes help solve your specific problem. Since no other common languages were initially aimed at parallel programming and do not facilitate it in any meaningful way, the need for it for people is not fully understood and understood.
“But I can do everything on callbacks in one thread,” they will say. And they do it, and it is painfully difficult. And you ask, “what happens if the callback gets into the loop or throws an exception?”, And if they don’t understand the question, then you have to work hard and explain the problem. But if the question is clear, then tell them that there is one distant country in which callbacks are not needed to program concurrency.
It seems that all of the above can be reduced to the following: please do not advertise Elixir as a functional programming language - it is not. It is a parallel programming language (CPL, Concurrent Programming Language).
Do not respond to arguments like "my functional language is more functional than yours." And do not even bother to talk about monads, immediately change the subject.
"- What is a CPL?"
"- You know, this is what WhatsApp is made on ..."
First of all, I would like to express my regret over the sudden death of Joe Armstrong - he died on April 20, 2019. It is difficult to underestimate his contribution to the development of the industry, as well as his talent as a popularizer - books, speeches, and active work in the Erlang and Elixir communities.