Developer

A Quickstart to Erlang

If any language could be said to be ideally placed to deal with the challenges of the next 10 years it's Erlang. Designed from the ground up to take advantage of parallel and multi-core architectures, and natively supporting distributed systems coding, Erlang is a valuable addition to your programming skill set.

If any language could be said to be ideally placed to deal with the challenges of the next 10 years it's Erlang. Designed from the ground up to take advantage of parallel and multi-core architectures, and natively supporting distributed systems coding, Erlang is a valuable addition to your programming skill set.

Originally designed by Ericsson as a proprietary language for controlling telecoms applications, Erlang was released to the public in 1998 under an open source licence. It's been gaining in popularity over the past few years largely due to its support for cheap, quick and disposable processes, which make adding and using concurrency in your programming easier and more efficient. Popular programs implemented in Erlang include ejabberd, the instant messaging server behind jabber.org, and Wings3D, a full featured 3D modelling application.

Why Erlang?

  • Parallel programming — It's the next big thing, and no language does it better than Erlang. Creating processes is easy, cheap and clean and manipulating them is not much harder. Best of all, since inter-process communication is conducted entirely by message passing and there is no shared state, many concurrency problems just go away.
  • It's functional — without the concurrency, Erlang behaves as a near pure functional language. Functional languages eschew state, which means that bugs have less chance of having unexpected side effects. The result is more robust and secure code.
  • It's free — Erlang is backed by open standards and free implementations of the interpreter. That means you can start working, learning and developing in Erlang for absolutely nothing.
  • It's tested — having been deployed in real world applications by Ericsson since the late '80s, you can be sure Erlang has got proven reliability and fault tolerance.

Where can you get it?

Erlang.org is the first place to look. There is a source distribution for Linux, UNIX and Macintosh systems, and a Windows binary.

Interactive Mode

Like many modern languages, Erlang comes with an interactive prompt, which allows you to test your program without having to change and recompile each time you want to test a new component or function. You can try it out to do some simple math operations — Erlang can handle numbers pretty much as big as you like, so don't be afraid to try those really long equations you've always wanted to:

nickg@nickg-desktop:~$ erl
Erlang (BEAM) emulator version 5.5.2 [source] [async-threads:0] [kernel-poll:false]

Eshell V5.5.2 (abort with ^G)
1> 10+5.
15
2> 15*3.
45
3> 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2.
99895953610111751404211111353381321783955140565279076827493022708011895642232499843849795298031743077114461795885011
932654335221737225129801285632

Each statement must be punctuated by a full-stop.

Functions

Erlang is a functional language, and so control flow is conducted using functions, pattern matching and recursion. Syntax in Erlang is very close to that of the declarative language Prolog. For example, type the following in a file called hello.erl.

-module(hello).
-export([hello/0]).

hello() -> io:format("Hello World~n").

This defines a module called hello, which exports (meaning, makes visible to code which imports the module) one function, also called hello, which takes no inputs. The hello function uses the format function from the io module, which is similar to printf, to print a string to the console. The "~n" is the sequence to print a newline, similar to "\n" in some other languages.

Load it into the interactive interpreter and try it out:

nickg@nickg-desktop:~/erlang$ erl
Erlang (BEAM) emulator version 5.5.2 [source] [async-threads:0] [kernel-poll:false]

Eshell V5.5.2  (abort with ^G)
1> c(hello).
{ok,hello}
2> hello:hello().
Hello World
ok

For longer functions, you separate statements with a comma, and only use the full-stop to denote the end of the function:

hello() -> 
	io:format("Hello "),
	io:format("World~n").

Erlang also supports pattern matching on function inputs, which allows you to write different versions of a function depending on the parameters. This allows you to write recursive solutions cleanly, like so:

countdown(0) -> 
	io:format("Blast Off!~n");
countdown(X) -> 
	io:format("~w~n", [X]),
	countdown(X-1).

2> test:countdown(10).
10
9
8
7
6
5
4
3
2
1
Blast Off!
ok

You can further enhance function input pattern matching by using guards — which let you specify criteria for the inputs beyond simple patterns. For example, our countdown function above can only handle positive numbers, but can be called with any number at all. We can use guards to protect it, and only let correct inputs through:

countdown(0) -> 
	io:format("Blast Off!~n");
countdown(X) when X > 0 -> 
	io:format("~w~n", [X]),
	countdown(X-1).

Alternatively, we could extend the countdown function to work for both positive and negative numbers by adding another version of the function:

countdown(0) -> 
	io:format("Blast Off!~n");
countdown(X) when X > 0 ->
        io:format("~w~n", [X]),
        countdown(X-1);
countdown(X) when X  
        io:format("~w~n", [X]),
        countdown(X+1).

Control Flow

Erlang also supports If statements, so you can branch inside functions without having to write a new function with pattern matching. To rewrite the last example of the countdown function using only one function implementation we could write:

countdown2(X) ->
    if
        X == 0 ->
            io:format("Blast Off!~n");
        X > 0 ->
            io:format("~w~n", [X]),
            countdown2(X-1);
        X 
            io:format("~w~n", [X]),
            countdown2(X+1)
    end.

In this case it's up to you which one is easier to read and maintain.

There are no explicit loops in Erlang, so when you want to do things repetitively you need to use recursion.

Processes

Erlang is all about concurrency, the preferred method for solving a problem is to export the work to a number of processes, which allows the program to take advantage of multi-core processors or distributed systems with no additional hassle. Lets look at an example:

-module(test).
-export([wait/0, send/1, start/0]).

wait() ->
    receive
        {word, X} -> 
            io:format("Got ~s~n", [X]),
            wait();
        stop ->
            io:format("End.~n")
    end.

send(Pid) ->
    Pid ! {word, "Hello"},
    Pid ! {word, "World"},
    Pid ! stop.

start() ->
    Pid = spawn(test, wait, []),
    spawn(test, send, [Pid]).

Here we have a function (start) which spawns two processes, the first simply waits until it gets a message of the format {word, X} and then prints it, the second process sends a few messages to test it.

Processes are spawned using the spawn function, which needs three arguments, the module where the function is, the function to be called in the new process, and a list of arguments for that function. If the function takes no arguments, the third argument of spawn should be an empty list.

To receive messages, you use the receive statement. Receive looks a lot like If, in that the first message encountered is matched against a series of patterns in the same way that If matches against a series of guards. In our wait function, we match the message against a pattern containing {word, X}. This is a tuple with two items, the first is an atom, starting with a lower case letter, and must be matched exactly, the second is a variable, starting with an uppercase letter, which can match anything. If we get the atom "stop" then we end the process.

To send messages you must use the send operator !. In Erlang, message passing is asynchronous, which means that the send operator will not wait for the message to be received and will continue on with its own execution. The send operator has two parts: The part before the ! is the process identifier, or pid, which is returned by the spawn function. The part after the ! is the message that you want to send — this can be any legal Erlang type.

If you type this program into your file test.erl and load it into the interpreter you should see the following:

nickg@nickg-desktop:~/erlang$ erl
Erlang (BEAM) emulator version 5.5.2 [source] [async-threads:0] [kernel-poll:false]

Eshell V5.5.2  (abort with ^G)
1> c(test).
./test.erl:35: Warning: variable 'Any' is unused
{ok,test}
2> test:start().
Got Hello

Got World
End.

We see the expect results, along with a strange output. This the value returned from the start function, which by default is the value of the last expression in the function — the pid of the send function — This is printed only in the interactive prompt, which prints the result of each expression back to the user, under normal circumstances this would not appear.

Final Thoughts

There you have it, Erlang in a nutshell. This guide should have given you the basic knowledge to write simple sequential or concurrent programs in Erlang. There's plenty more to the language however, including list comprehensions, error handling primitives and records. For more information you can consult the Erlang Reference Manual or stay tuned to Builder AU in the coming weeks for more Erlang material.

Editor's Picks

Free Newsletters, In your Inbox