Joe Armstrong, co-creator of Erlang, writes about programming, concurrency, Elixir, and small programs on his GitHub-hosted blog.
Commenters often point to his post "My favorite Erlang Program" as a clear explanation of what makes Erlang and Elixir powerful.
This was sort of true when computers had few CPUs/cores. It didn't make much of an efficiency difference, it was mostly a question of programming model. It works fine as long as the program is fundamentally I/O bound, but breaks down when it is doing actual work and becomes CPU bound.
I have certainly had some horrible experiences debugging multi-threaded C++ programs, and using non-blocking I/O made them safer and easier to reason about because only one thing happens at a time. The non-blocking I/O programming paradigm, however exposes unnecessary "plumbing" to the programmer.
What we really want is a concurrency model where we can handle each request as if it was the only thing happening.
To the extent that multiple requests need to share resources, we need ways to safely access state with concurrent access. That might be a relational database, mutexes, or software transactional memory.
I am currently in the middle of updating a large application written in Twisted Python. async/await and promises can certainly be complex. The Flask approach of using one thread per request is easier to understand. Everyone in the Javascript is in love with async/await, but I can see where that ends: just look at what Twisted was doing 10 years ago. And see that it basically failed due to complexity.
The model I like best is Erlang/Elixir. The runtime handles I/O using non-blocking I/O and threads to be efficient. The programmer works in terms of lightweight actors (called "processes",…
A flag function that decides a boolean decision could have a signature such as f: context_t -> bool where context_t is a value type containing fields such as: uuid of the current user, uuid of the node or region we are deployed to, the current time, the current version of the application code.
Feature flag platforms such as launch darkly can be thought of as a way to manage and deploy new implementations of decision functions into running application processes. E.g. dream up a class of decision functions with the signature f: context_t -> bool that could be serialised and sent over the wire between two machines.
For large muddled IT organisations, toggling a flag in a production application by having a developer hardcode it or toggling a flag by changing static application config and redeploying might require 15 minutes of development time followed by days of integration testing and meetings and change approval lead times. In these settings, having some kind of feature flag platform deployed that allows application behaviour to be toggled very rapidly without coupling it to some kind of IT software deployment might let the organisation react and run experiments two or three orders of magnitude faster. Give product managers or "the business" the ability to adjust application configuration live in production with the feature flags without having layers of slow process in the way.
If your application contains a large subsystem where some decision or logic is evaluated by…
When you're talking about type systems, "dynamic" really doesn't make much sense to talk about. It's not like the runtime constructs a typing model out of its observations of the properties of objects' runtime interactions. The notion of there being a "type" to a duck-typed object is purely a theoretical one; in practice, the object just does whatever it wants moment-to-moment, and the runtime has no idea.
Consider a generic "proxy" object that can be arbitrarily disconnected and reconnected to objects of different types. These can exist in any duck-typed runtime system. What is such an object's "type", even in the sense of its "runtime type"? There isn't one. There might be a sense in which it has an instantaneous type—a type it has as of a given program world-state—but that information is inaccessible to the runtime, since any probing it might do to ascertain this might also cause the object's instantaneous typing to change in the middle of the probing procedure.
(See also: the Universal Server in Erlang [ https://joearms.github.io/published/2013-11-21-My-favorite-erlang-program.html ]. What is this server's "type"?)
A type system is something that can make guarantees about the behavior of a program in advance. In that sense, duck-typing isn't really a type system. It's just asking objects questions and then blindly trusting the responses you get. There's nothing but convention guaranteeing that an object that e.g. in Ruby implements `respond_to?` a certain way, will…
Joe Armstrong - the creator of erlang would turn his cluster of 1000's of machines to change behaviour. The code is really 5 lines.
My favorite Erlang program
21 Nov 2013
The other day I got a mail from Dean Galvin from Rowan
University. Dean was doing an Erlang project so he asked
“What example program would best exemplify Erlang”.
...
The Universal Server
Normally servers do something. An HTTP server responds to HTTP requests
and FTP server responds to FTP request and so on. But what about a Universal
Server?
surely we can generalize the idea of a server and make a universal server that
which we can later tell to become a specific sever.
Here’s my universal server:
universal_server() ->
receive
{become, F} ->
F()
end.
...then I set up a gossip algorithm to flood the network with become messages.
Then I had an empty network that in a few seconds would become anything
I wanted it to do.
a process in erlang, is nothing but a tail-recursive function. the moment it stops being so - it dies. so here it morphes into F; which can be passed in.
more at http://joearms.github.io/2013/11/21/My-favorite-erlang-program.html
> Also, I find Armstrong's fanaticism grating, and am inherently distrustful of anybody who claims that their community and language has all the good ideas. Because odds are, they're wrong.
You might find this[0] blog post by Armstrong interesting, wherein he comments on some things that were/are done wrong in Erlang. I would also argue that this 'fanaticism' is made to look more severe as you can find at least 4 different talks where Armstrong argues for the same things over and over.
In any case, Armstrong is actually very humble, which I think seems fairly obvious if you actually watch a few talks and read more than a couple of blog posts by him.
Could you point to something specific where you feel Armstrong misrepresents a strong side of Erlang, or is it just a general thing?
(Edit: Just to add, I think it should be said that the Erlang team created their favorite language and that it probably represents the most useful language in use today to them, so I don't think it's surprising that they'd see more good ideas there than in any other language. On top of that Armstrong is a very straight shooter, it seems, so I think this might be something to take into account.)
0 - http://joearms.github.io/2013/05/31/a-week-with-elixir.html
The Joe Armstrong blog post linked by another commenter above actually addresses some of this: https://joearms.github.io/#2013-05-31%20A%20week%20with%20Elixir
TLDR: GC and runtime behaviour generally are built from the ground up in OTP with this kind of concurrency and programming model in mind. Its advantages can be approximated but not fully replicated in "general purpose" runtimes like the JVM.
Consider that the JVM model is for long-running shared memory systems. So its GC in particular is built around that model. Erlang/OTP as I understand is a lot of short lived processes that communicate through messages, sharing little state. Designing a GC for a system like that has entirely different trade-offs. Isolated short lived actors can throw-away their entire memory state at process end, without waiting for a generational collector to discard the garbage, etc.
And that's just the GC. In general in a system bolting "actors" onto another shared memory language it's always going to be possible to "escape" that framework and do things in another paradigm. That might be fine for the real world, but it negates some of the advantages that OTP brings to the table.