An Erlang Tutorial

Madanasekaran.P

Introduction :

Erlang can be described as under:

  • Language developed at Ericsson Telecom
  • It is a simple dynamically-typed functional programming language
  • Concurrent, with light-weight processes
  • “Share nothing” process semantics
  • Pure asynchronous message passing
  • Transparent distribution of processes across machines
  • Mechanisms for in-service code upgrade
  • Large set of libraries (OTP).

Though the first version of the language appeared in 1986, its use till 2000s was limited. It was in use in some projects including Ericsson’s broadband, GPRS, and ATM switching solutions. Certain fortuitous circumstances changed its fortunes.

  •  Banned within some groups at Ericsson, it was released as open source in 1998.
  • Two developments in 2000s had telling effects. a) Explosion in the number mobile clients to web apps – the so called “C10K” problem. b) Advent of multi-core computers

The Servlet technology with its multi-threading/ “one thread for one connection” model with shared memory was found to be inadequate to handle “C10K”. Parallelizing shared memory code is also very hard. In Erlang’s light weight “process”/actor model, one OS thread takes care of many independent asynchronous message-passing “processes”.  With no shared state, it can scale well to service millions of connections. Its transparent distribution of processes across machines enabled deployment of programs written for single core without any change of on multi-core machines. As on date most of the high-traffic sites use Erlang OTP( an Erlang distribution) or Akka framework on JVM  built with Scala, another functional language  and follows the Erlang actor model. There is paradigm shift from Object Oriented to Functional and Concurrent Programming. WhatsApp, FaceBook chat, Heroku, Couchbase, Riak and many more use Erlang. Amazon uses Akka. Twitter uses Finagle another framework built with Scala. All these frameworks fall into the category “Reactive”-IO is asynchronous and non-blocking and a small number of OS threads handle many actors/event-handlers and is able to scale to service millions of concurrent connections. Spring, the popular Servlet based technology is expected to go reactive in Version-5.As on date there are only two reactive frameworks for Java – Vert.x from Red-Hat employees, and Reactor from Spring Source. Though Akka can be used in Java, it is mainly for Scala and all the materials available are for Scala only. We already had a series of articles on “Scala” and “Akka”. We will have a series on Vert.x. We will have a look at “Erlang”, the first Reactive framework. Recently there is another language for Erlang Virtual machine (EVM)   “Elixir”- with simpler, Ruby-like syntax but Erlang compatible. We will see about that also, if necessary

Some History

In 1986 the team of Joe Armstrong, Robert Virding, and Mike Williams developed the first version of Erlang at Ericsson. They continued to develop and polish it through the last half of the decade. Through the 1990s, it grew in fits and starts and gained still more traction in the 2000s, after the “C10K”. Now its users list is impressive. The buzz for Erlang is growing steadily because it Erlang OTP is the first reactive framework and the need of the hour is “Reactive frameworks “,  which provide concurrency, scalablity, and reliability. Erlang was built for Concurrency. Erlang is a product of years of research from Ericsson to develop near real-time fault-tolerant distributed applications for telecom applications. The systems often could not be taken down for maintenance. Ericsson studied programming languages through the 1980s and found that, existing languages were inadequate for their needs. These requirements eventually led to the development of an entirely new language. Erlang is a functional language—one with many reliability features baked in. Erlang can support reliable systems. One can’t take a phone switch down for maintenance, and one doesn’t have to take Erlang down to replace entire modules. Some of its applications have run for years without ever coming down for maintenance. But the key Erlang capability is concurrency. The multi-threading approach to concurrency of “C” languages was the main approach till “C10K” in 2000s. Now the approach of Erlang-many independent light weight processes/actors within a thread that communicate only through “asynchronous” messaging has found favor, as mentioned above. Akka on JVM has already taken this route and found success. Other JVM frameworks also try to follow it and we will see about them separately and now we will focus on Erlang.

Error-handling in Erlang

The Erlang believes in “Let it crash.” Since Erlang makes it easy to monitor the death of a process, killing related processes and starting new ones are easily done. One can also hot-swap code, meaning one can replace pieces of one’s application without stopping one’s code. This capability allows far simpler maintenance strategies. Erlang combines the robust “Let it crash” error strategies with hot-swapping and lightweight processes that one can start with minimal overhead. It’s easy to see how some applications run for years at a time without downtime. But it is the concurrency model that is compelling. The important primitives— message passing, spawning a process, monitoring a process—are all there. The processes that one spawns are lightweight, so one doesn’t have to worry about constrained resources in this area. The language keeps side effects and mutability to a minimum and monitoring the death of a process is simple. All necessary tools are in one package –Erlang OTP.

Erlang and Multicore:

The Erlang model for concurrency—separate processes with no shared memory communicating via message passing—naturally transfers to multi-core processors in a way that is largely transparent to the programmer, so that you can run our Erlang programs on more powerful hardware without having to redesign them. Symmetric multiprocessing (SMP) support in Erlang also contributes to this. The goal of Erlang’s SMP is to hide the problems and awareness of SMP from the programmer. Programmers should develop and structure their code as they have always done, optimally using concurrency and without having to worry about the underlying operating system and hardware. As a result, Erlang programs should run perfectly well on any system, regardless of the number of cores or processors

Downloading and having a look

For Windows “Erlang OTP” is available as “exe” and you can download it and install it. Edit the system variable “path” to include the Erlang/bin. You may have to restart the system. The installation comes with the shell and it will be available in your Programs menu. Open it. It may appear as shown below:

Try some code.

2 + 2. % see the use of “.” to end the expression. This is a comment
4
2 + 2.0.
4.0
One.
*1: variable ‘One’ is unbound.
One = 1.
1
Two = 2.
2
Two = Two + 1.
** Exception error No match of Right hand value three.

Bear in mind the following:

  1. Variable name starts with a Capital letter(One).
  2. “=” is not an assignment operator but a matching operator.
  3. If the values on the two side match it will execute. Otherwise it will throw error  as shown above. Hence there is no “reassignment” of variables, found in Imperative languages.

Atoms:

Type “blue.”  Or ‘blue’. in the shell. It will return blue. It is an atom similar to CONSTANTS in C. It can be defined with or without single quotes but unlike a variable it should start with “lower-case” letter. Reserved words are atoms and you should use them in naming your atoms. List of reserved words are:
after and  also band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor

Boolean and comparison Operator.

The comparison operators are “ =: =”, “==” .They return a boolean as shown below:

5 =:= 5.
True
5=:=5.0. % not exactly equal but equal
false
5 == 5.0
True

 “String” .
There is no string but only a list of characters.
“hello”.
“hello”

Tuples: They are similar to structs in C. It can be used to group some data as shown below:

Point = { 3, 4}. % curly braces used to define Tuples.
{3 ,4 }
{X , Y } = Point. % one form of Pattern matching.
{3, 4}
X.  % extracts value from the Tuple.
3

Tuples are of fixed length and are used in pattern matching. When you match a tuple, the size will matter. You can’t match a three-tuple to a two-tuple.

Elements within a tuple can be of different types:

T = { ram,24,2.4,{samy,1}}. 
The function element() can get the element if you specify the position.
element(1,T).
You can change the value of element in Tuple but you have to assign
the tuple to a new variable as shown below:
T2 = setelement(2, T,99).
T does not change.
There is function tuple-size to find out the size of a tuple.
tuple_size(T).

List:

Let us have look at “List”.

It can be created using “[]”.
[1, 2, 3].
[1, 2, 3]
[2,6,’ hello’]. % can mix types
[2,6,hello]
L1 = [2,[1,2],[3,4]]. % contains sub-lists

 “++”  appends to list “- - “removes elements from a list.
“hd’, “tl” functions work as under:

hd([1,2,3,4]).  % returns first element
1
  tl ([1,2,3,4]).   % returns Rest
[2,3,4]

List library functions 

List library comes with a number of library functions like max(),sort(),reverse etc .
We will see them.

L2 = [ 4,8,1,2,10].
lists:max(L2).
10
lists:sort(L2).
[1,2,4,8,10]
You can assign the sorted list to another variable
L3 = lists:sort(L2).
[1,2,4,8,10]

lists:reverse(L3).
[10,8,4,2,1]

Anonymous Functions:

Named functions are defined in module and exported for use outside. We will see anonymous/nameless functions first.

Numbers = [1,2,3,4].
[1,2,3,4]
lists:map(fun(X) -> X + 1 end, Numbers).
[2, 3,4,5]

The key-word “fun” denotes an anonymous function. It takes “X” variable as argument and returns X + 1.You can see similarity to Scala syntax we saw earlier but without types for variables. As Erlang is a dynamic language, it will infer types of arguments from the value passed for parameter or value returned. As in Scala there is a no “return” key word The value returned by the last expression is the return value of the function – here is only one expression here. Lists:map() is a higher order function as it takes another function as parameter.

Let us have a look at another anonymous function. This time it is assigned to a variable. The Variable name can be used like a function name.

Small = fun(X) -> X < 3 end.
lists:filter(Small, Numbers).
[1,2]
The function was passed to lists.filer() with the Variable name.
lists:all(Small, [0, 1, 2]).
true
lists:all(Small, [0, 1, 2,3]).
False.
lists:foldl(fun(X, Sum) -> X + Sum end, 0, Numbers).
10
list:foldl() is another higher order function. The variable “Sum” is used as an accumulator.
There are functions like sort(),sort(),reverse() etc in the lists module

List Comprehension

As in other functional languages Erlang also uses a modified Mathematical ”Set” syntax for List Comprehension. See below:

[2* N || N <- [2,3,4,5]].
[4,6,8,10]
What happens. <-  means in or belongs to. || means goes to. Here each element of List goes to the Computation 2 * N. A new list is generated.  Instead of sending each element we can put some guards/filters.
[X * X || X <- [2,3,4,5], X rem 2 =:= 0].
Here the new list consists of squares of only even numbers.
X <- [2,3.4] is called Generator expression. You can have more than Generator in your Expression. Generator Expression coupled with Pattern Matching acts as a filer as shown below:
Weather = [{chennai, sun}, {nellore, storm}, {cochin, rain}, {simla, snow}, {gangtok, fog}].
A list consisting of Tuples will be created. Now you filer the list for FoggyPlaces as under:
FoggyPlaces = [X  ||  {X, fog}  <- Weather ].
[gangtok]

IO library  See the examples below:

L  =  io:get_line(“prompt:”).
prompt:
“Hello\n”
io:format(“~w ~w  is my name ~n”, [madan, sekaran]). % similar to printf in C
madan sekaran is my name

Compiled programs.

In Eclipse erlide go to New -> Erlang Project. Give the name as “LrnErlang” and Click Next. You can see Project layout configuration wizard as under:

Click Finish. You may Project files as shown in the wizard. Right click on src and choose New à Module. Give the name as “easy” and click Finish. The file  “easy.erl” will be generated.
To the file

  •  Add a function add(X,Y) -> X + Y.
  •  Include it in export([]).

After doing the above, the easy.erl may look as under:

%% @author admin
%% @doc @todo Add description to easy.

-module(easy).

%% ====================================================================
%% API functions
%% ====================================================================
-export([add/2]).  %% /2 shows add()  takes 2 arguments

%% ====================================================================
%% Internal functions
%% ====================================================================
add(X,Y) -> %% Head
X + Y.   %% Body

Compile

To compile the file do the following in the IDE.

  • Right click on the project and choose Run As -> Erlang Application. Now the Erlang Shell will appear in Console. Change to the directory in which “easy.erl” is available by typing

cd(“E:/lunaspace/LrnErlang/src”).  % Note Forward slashes and quotes and modify the command for your directory
Press Ctrl + Enter.
The directory will change; if does not change check whether there is any error.
Now compile
c(easy).
Press Ctrl + Enter.
You can see “easy.beam”  under “ebin”.
Now you can call the function in the console
easy:add(2,3).
Press Ctrl + Enter.
5
Code a recursive  function “factorial” as under:

factorial(N) when N > 0 ->
N * factorial(N - 1);
factorial(0) ->
1.

Add it to exports list. The file may look as under:

..
-module(easy).

%% ====================================================================
%% API functions
%% ====================================================================
-export([add/2,factorial/1]).

%% ====================================================================
%% Internal functions
%% ====================================================================
add(X,Y) -> %% Head
X + Y.   %% Body

factorial(N) when N > 0 ->
N * factorial(N - 1);
factorial(0) ->
1.

Now re-compile the easy and run easy:factorial(5) and see the result as 120.

We can add one more function using Control Structure “case”.

area(Type, X, Y) ->
case Type of
square -> X * X;
circle -> math:pi() * X * X;
triangle -> 0.5 * X * Y
end.


Add to the exports([ , area/3]).

From the shell recompile the file and call easy:area(circle,7,0).% function requires three parameters. So “0” is given as a dummy parameter-not taken for calculation.

Conclusion

Erlang is a dynamically-typed functional language with a stress on immutability and no shared state between its “small” processes that communicate only through messaging. A Variable need not be declared before-hand. When it is used, the type will be inferred. The data types are similar to ones found in other languages. It has two equality operators. Other operators are as in any other language. Being a functional language it does not support reassignment of a variable. The operator”=” is actually a matching operator and pattern-matching is important as in any other functional language. Functions, anonymous functions, higher order functions are available as in other functional language. Tuple (fixed size) and List are important data structures. We had a look at some of the functions in list module. List Comprehension is another important construct in Functional languages. A function defined in a module and exported can be re-used. We saw how to create the module in a file and compile it and use the function in it..

Erlang was created when tried to solve the problems of a more advanced telephone –systems. Prototypes in a number of languages were created and tried, as every required feature could not be found in a single existing language, though some features were available in some languages. For example PLEX, the earlier language used in Ericson had the following properties:

  • Fine grained massive concurrency 2) independent isolated software bocks 3) update code at run time without stopping 4) run-time tracing 5) restart mechanism.

But it is not high level and fast enough for advanced systems. It is an imperative pseudo-parallel language fit for the limited hardware of 1970s.In Ericson asynchronous messaging with no shared memory was used by the nodes distributed in far off places for communication for quite some time. They are looking for solution with these features but a more efficient implementation. Functional languages like Miranda and ML were also tried. Finally they zeroed on a Prologue prototype and started adding features to it. Prologue interpreter was used in earlier versions and later on it was replaced by VM written in C. The Erlang language was developed to meet the demands of Telecom industry which demanded massive concurrency and error- recovery.  You can see after the “C10K”problem, soft real-time systems in web services, retail and commercial banking, computer telephony, messaging systems, and enterprise integration, to mention but a few, happen to share the same requirements as telecom systems. This explains why Erlang is gaining headway in these sectors .Erlang is not suitable for writing a number-crunching application, a graphics intensive system, or client software running on a mobile handset, It meets well the demands of high-level, concurrent, robust, soft real-time system that will scale in line with demand, make full use of multi core processors, and integrate with components written in other languages. Tim Bray director of Web Technologies at Sun Microsystems said in 2008 that “If somebody came to me and wanted to pay me a lot of money to build a large scale message handling system that really had to be up all the time, could never afford to go down for years at a time, I would unhesitatingly choose Erlang to build it in”. We will see about its concurrency and error-handling in detail in future.








}