This is the definitive book on Erlang, written by Joe Armstrong, the creator of the Erlang language. The book is clearly written, with lots of small examples, and paced for the beginning Erlang programmer.
Erlang takes a little getting used to. It is a functional language, meaning that functions in general are unable to cause side-effects. For example, ‘variables’ are in one of 2 states: their initial state is ‘unbound’, their final state is ‘has some value that can never change’. Attempting to place a value into a variable that already has a value causes an exception. This aspect of functional programming makes it possible to write multi-threaded/multi-process applications without the problems inherent in multi-threaded applications in non-functional languages.
The basic data types in Erlang are functions, atoms, numbers, lists, tuples, and strings (which are actually lists of integer numbers). List manipulation in Erlang is similar to that in Lisp: lists are generally treated as a head and tail. This is used by the Erlang way of defining functions: functions are defined as a set of pattern-matched expressions with code associated with each expression. For example, a simple accumulator in Erlang might look as follows:
total([H|T:]) -> H + total(T); total([:]) -> 0;
total([1,10,20,5). ====> 36
This just says that to sum the values in a list, you add the value of the head of the list to the sum of the values in the tail, and that the sum of an empty list is zero.
Functions (lambdas, really, or ‘funs’ as they are called in Erlang) are first-class objects in Erlang, meaning that they can be members of tuples and lists, can be passed as parameters to functions, and can be returned as a value by functions. So, for example,
Double = fun(X) -> ( 2 * X ) end.
Double(5). ====> 10
Erlang was designed from the beginning to make it easy to write concurrent programs. Erlang process creation is very efficient, and there is no great difference between running such a program as many threads on one box or many processes on multiple boxes. A new process is created with the spawn function, which takes a fun (a lambda) as a paramter. The spawn function returns the process id (pid) of the new process, which may then be used to communicate with that process. The book shows a couple simple examples of distributed programming by way of illustration: a simple name server, and a stripped-down IRC server and client.
The book continues with details on how to interface C and Erlang software, how to communicate over TCP and UDP, the Erlang large-data storage mechanisms (ETS an DETS), and the Erlang database (mnesia).
There is a nice example of implementing map-reduce for disk indexing with Erlang on a multicore system.
Finally, there are a number of appendices including a large reference listing of the standard Erlang modules and functions.