Our reading group on Bainbridge Island has been working its way through Programming Erlang. Actually we’re technically not done yet, but since I spent a fair amount of time on the ferry recently, I went ahead and finished it off. There’s been quite a bit of writing about Erlang recently, and I wanted to at least have finished the book before jumping in. Looking at Joe Armstrong’s PhD thesis is probably soonish on my list too.
Erlang is a functional language which incorporates a concurrency model based on very lightweight processes communicating via messages. I’ll cover the concurrency model a bit more below. Since many people have not really been exposed to functional programming, there are things in Erlang which seem odd when compared to more mainstream languages. In addition, Erlang relies heavily on pattern matching as a flow of control construct, and it takes some time to get used to it. Some people liken the pattern matching aspects of Erlang to Prolog, but this is not entirely accurate because Prolog uses unification, which works in “both directions” and not pattern matching, which only works in “one direction”. I can’t say that I care for the syntax of Erlang, but after using Python, there are very few syntaxes that I really like. Erlang supports higher order functions, so closure based control flow structures are included. There is a fairly usual set of basic data types which are provided. Probably the biggest problem with the basics of Erlang is the way that strings are handled. In reality there are no strings in Erlang, and strings are just lists of integers. More on that below.
Much of the current interest in Erlang is due to its concurrent programming capabilities. The foundations of these capabilities are the availability of processes at the language level. Erlang allows a programmer to create and destroy processes quickly and cheaply (in terms of resources). Processes can only communicate with each other by sending each other unidirectional messages. Every process has a mailbox, which is where messages for it are delivered. The messages are queued there until the process explicitly “receives” them.
The code that implements a process typically consists of a tail recursive loop which explicitly “receives” messages and uses pattern matching to examine the messages and dispatch to the correct behavior. Replying to the sender of a message must be handled by the programmer, but it is easy to code up simple rpc style message passing. Two (or more) processes can be linked to each other so that when one process dies, the other is sent a signal. The preferred mode of handling errors in processes is to kill them and restart them. This signaling forms the basis of the supervision tree concept in OTP. The basic concurrency model of Erlang is a version of the Actor model developed by Carl Hewitt at MIT. I took Hewitt’s class while I was an undergraduate, so the concepts were familiar to me. Erlang is relatively blind to where a process might be running – in the same VM, in a different hardware thread on the same VM, or on a VM on different computer altogether. This makes it easy to write programs that can grow easily when you want to add hardware, whether that is processors or computers.
The folks at Ericsson have also provided a bunch of libraries to raise the level of abstraction for concurrent programming in Erlang. There are 3 major libraries. OTP (Open Telecom Platform) helps a programmer to write scalable, fault-tolerant code. It takes advantage of Erlang’s hot code update facilities to allow processes to be upgraded in place. The basic abstractions to do this are very simple to work with. OTP includes the notion of supervision trees, which is an abstraction for managing networks of processes.
Mnesia is a (potentially) distributed database written in Erlang. It provides an easy mechanism for storing Erlang terms. While it is not an RDBMS, it does provide a query mechanism based on list comprehensions. It also supports transactional behavior and has the ability to duplicate Erlang tables on other machines
One thing that isn’t discussed enough are the features of the Erlang runtime/VM. The runtime is very efficient at managing processes, much more so that languages like Python, Ruby, or Java. Erlang programs have been deployed in telephone switching products for years, with extremely long uptimes – due in part to Erlang’s hot code swapping capabilities. Java’s hot code replacement or Python’s reload are substantially weaker than Erlang’s hot code swapping. So while libraries that provide an actor like model can help people learn a good programming model for concurrency, it’s less clear to me that the languages (and the implementations of those languages) hosting the libraries will be as good as Erlang when it comes to highly concurrent applications. Of course, if an application isn’t that concurrent it might not matter.
Semantically, there is a lot to like about Erlang – the actor based concurrency model, hot code swapping, higher order functions, and (once one gets used to it) pattern matching. The OTP libraries have been refined by many years of production usage in demanding, commercial applications.
At the same time, there are number of issues which I think are real barriers to Erlang adoption. The syntax will prove difficult for many people, which is a big issue. I’ve already mentioned the problems with string handling, and really that generalizes to a lack of libraries for performing 21st century / web computing tasks. The nice thing about telephone switches is that you don’t really have to talk to the world. But if Erlang is to be viable as a solution for mainstream programming as it moves to more concurrency, Erlang programs must be able talk to the environments around them.
I am aware of several projects where Erlang is being used to do the heavy server lifting and then data is being passed off to programs written in more familiar languages like Python, Ruby, or Java. Certainly this is one way that people could begin to exploit the benefits of Erlang without converting wholesale. It would also give the Erlang community some time to improve Erlang to the point where it could be adopted by a larger audience.