Erlang in Real Time

Mauri e Castro
1998, 2001
Copyright

This is the se ond draft of this book and has been used in the ourse `CS584
Real Time and Con urrent Systems' at RMIT University.

Erlang in Real Time
Mauri e Castro

1998, 2001
Copyright
Department of Computer S ien e
RMIT
124 Latrobe St
Melbourne VIC
Australia
ISBN:
Mauri e Castro
Department of Computer S ien e
RMIT
GPO Box 2476V
Melbourne VIC 3001
Australia
mauri eser .rmit.edu.au

Prefa e
Why Erlang?

In 1984 Eri sson ondu ted a series of experiments using a range of programming languages and programming te hniques to identify the qualities required in
a software development environment for tele ommuni ations appli ations. The
experiments in luded imperative, fun tional and logi languages, and rule based
and obje t oriented te hniques. At the on lusion of the experiments there was
no existing language with all the required features, however, the fun tional
programming languages showed promise as they resembled existing imperative
programs and allowed fun tions to be easily ombined while preserving orre tness.
The Erlang language is designed to meet the requirements of a telephony
environment. On the te hni al side telephony software must meet soft real-time
timing onstraints, support on urrent programming, and provide a means for
repla ing running ode. When making a telephone all lients expe t results
within a short period of time. To ensure that servi e is delivered within lient
expe tations, it is ne essary for the programmer to be able to spe ify a tions
that o ur within a given time and to program rea tions if these a tions do not
o ur. In addition, telephone ex hanges have an inherent parallelism in that
many similar a tions must be handled at the same time, typi ally the making
and re eiving of telephone alls. The software used in telephone ex hanges runs
for long periods of time, and in general an ex hange annot be shut down to
allow for software hanges. This hara teristi makes it ne essary to me hanism
that allow software to be updated on the y. On the management side, the programming language must support large teams of programmers, require minimal
e ort in the systems integration phase of development, and be easily and qui kly
taught. The development and maintenan e of tele ommuni ations produ ts are
large s ale endeavours of great omplexity. To meet the hallenge of assembling
these produ ts in a timely fashion large teams are ne essary, furthermore, redu ing the ost of putting together the parts made by members of the teams
eliminates a signi ant development ost. Finally, if a spe ial purpose language
is used, short training time allows the produ tivity bene ts of the language to
be gained at a minimal ost and allows large numbers of programmers apable
in the language to be pro ured in a reasonable time.
Erlang is a small on eptually simple language that meets these requirements.
i

ii
Languages

In addition to Erlang this book will use several programming languages in luding C, Ada and Java to illustrate on epts in a onventional programming
environment. A subsidiary aim of this book is to en ourage the reader to arry
on epts developed in Erlang into other programming languages. Although
these languages may not enfor e the dis ipline of Erlang, the restri tions imposed by Erlang are often helpful in redu ing oding and debugging when arried
out in other languages.
Approa h

The fo us of this work is on the transition between programming in pro edural
languages and programming in a de larative fun tional language. This leads to
an unusual approa h to introdu ing the Erlang language. Early examples tend
to have a greater number of if statements and use pattern mat hing in the heads
of fun tions less than the best of Erlang programmers would. This style is a
ompromise between the imperative programming approa h and the de larative
approa h and is used while introdu ing the building blo ks of the language.
Hopefully this approa h should make the early hapters less intimidating to
programmers making the transition from an imperative languages to Erlang.
Getting Erlang

Eri sson has released a number of implementations of Erlang under a free of
harge li ense. Further information about these implementations an be found
at:
http://www.erlang.se/erlang/sure/main/download/
Other Resour es

Further information on the language an be found in the original Erlang book
`Con urrent Programming in Erlang' by Joe Armstrong, Robert Virding, Claes
Wikstrom and Mike Williams and published by Prenti e-Hall. The rst part of
the book has been made available online at:
http://www.erlang.se/erlang/sure/main/news/erlang-book-part1.ps
http://www.erlang.se/erlang/sure/main/news/erlang-book-part1.pdf

The book itself is available in print:
Joe Armstrong, Robert Virding, Claes Wikstrom and Mike Williams
`Con urrent Programming in Erlang'
Se ond Edition
Prenti e Hall
Englewood Cli s, New Jersey
ISBN: 0-13-508301-X

iii
A knowledgements

The author was fortunate to have the assistan e of Torbjorn Tornkvist from
Eri sson's CS labs to larify aspe ts of the Erlang programming language and
its use.
The author also wishes to thank Doug Bagley for his proof reading of the
do ument.
Thanks also to Ri hard O'Keefe for his suggestions on writing truly fun tional solutions.

iv

Contents
Prefa e

i

1 Introdu tion to Erlang

1.1 Programming Environment . . . . . . . . . .
1.1.1 Starting and Leaving the Erlang Shell
1.1.2 Fun tions Provided by the Shell . . .
1.1.3 Compiling and Running Programs . .
1.1.4 Starting Additional Shells . . . . . . .
1.2 Anatomy of An Erlang Program . . . . . . .
1.3 Fa torial: The Classi Re ursion Example . .
1.4 Anatomy of a Fun tion . . . . . . . . . . . . .
1.5 Resour es . . . . . . . . . . . . . . . . . . . .
1.6 Exer ises . . . . . . . . . . . . . . . . . . . .

2 Fundamentals

2.1 Data Types . . . . . .
2.1.1 Integers . . . .
2.1.2 Floats . . . . .
2.1.3 Numbers . . .
2.1.4 Atoms . . . . .
2.1.5 Pids . . . . . .
2.1.6 Referen es . . .
2.1.7 Tuples . . . . .
2.1.8 Lists . . . . . .
2.2 Variables . . . . . . .
2.3 Memory Management
2.4 Fun tions . . . . . . .
2.5 Guards . . . . . . . . .
2.6 Modules . . . . . . . .
2.7 Built In Fun tions . .
2.8 Resour es . . . . . . .
2.9 Exer ises . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

3.1 Pro edural versus De larative
3.2 A Taxonomy of Fun tions . .
3.2.1 Transformation . . . .
3.2.2 Redu tion . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

3 Writing Fun tions

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

v

1

1
1
1
2
2
2
6
6
7
7

9

9
10
10
10
11
11
12
12
13
15
17
17
18
19
20
22
22

23

23
26
27
27

vi

CONTENTS

3.2.3 Constru tion . . . . . . .
3.2.4 Redu tion / Constru tion
3.3 Resour es . . . . . . . . . . . . .
3.4 Exer ises . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

5.1 Pro esses . . . . . . . . . . . . .
5.1.1 Finding a Pro esses Name
5.1.2 Pro ess Di tionary . . . .
5.1.3 Message Bu er . . . . . .
5.2 Messages . . . . . . . . . . . . .
5.3 Time Delays . . . . . . . . . . . .
5.4 Distribution . . . . . . . . . . . .
5.5 Registered Names . . . . . . . . .
5.6 Resour es . . . . . . . . . . . . .
5.7 Exer ises . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

4 Choi es
4.1
4.2
4.3
4.4
4.5

If . . . . . . . .
Case . . . . . .
Fun tion Heads
Resour es . . .
Exer ises . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

5 Pro esses and Messages

6 Meta-programming

27
30
32
32

35

36
36
37
40
40

43

43
43
45
45
45
48
48
51
51
52

53

6.1 Resour es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.2 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

7 Writing EÆ ient Code
7.1
7.2
7.3
7.4

Last Call Optimisation .
Hashable Constru tions
Resour es . . . . . . . .
Exer ises . . . . . . . .

8 Robust Programs
8.1
8.2
8.3
8.4
8.5
8.6
8.7
8.8
8.9
8.10

Cat h and Throw . . . .
Termination . . . . . . .
Error Handlers . . . . .
Defensive Programming
Linked Pro esses . . . .
Trapping Exits . . . . .
Robust Servers . . . . .
Generi Servers . . . . .
Resour es . . . . . . . .
Exer ises . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

57

57
58
62
62

63

63
67
69
70
70
72
72
74
76
76

vii

CONTENTS

9 Code Repla ement
9.1
9.2
9.3
9.4
9.5
9.6

Loading and Linking
Code Repla ement .
Limitations . . . . .
Code Management .
Resour es . . . . . .
Exer ises . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

10.1 Comments and Do umentation
10.1.1 Comments . . . . . . . .
10.1.2 Attributes . . . . . . . .
10.2 Modules . . . . . . . . . . . . .
10.3 Fun tions . . . . . . . . . . . .
10.4 Messages . . . . . . . . . . . .
10.5 General . . . . . . . . . . . . .
10.6 Resour es . . . . . . . . . . . .
10.7 Exer ises . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

10 Programming Style

11 Graphi s

11.1 Model . . . . . .
11.2 Interfa e . . . . .
11.2.1 Fun tions
11.2.2 Obje ts .
11.2.3 Events . .
11.3 Example . . . . .
11.4 Resour es . . . .
11.5 Exer ises . . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

Basi Fun tions . . . .
A Simple Web Server .
Resour es . . . . . . .
Exer ises . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

13.1 No Re overy . . . . . . . . . . . . . .
13.2 Ba kward Error Corre tion . . . . . .
13.2.1 Simple Retransmission . . . . .
13.2.2 Retransmission with Windows
13.3 Forward Error Corre tion . . . . . . .
13.4 Resour es . . . . . . . . . . . . . . . .
13.5 Exer ises . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

12 Internet
12.1
12.2
12.3
12.4

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

13 Reliable Communi ations

14 Reliability and Fault Toleran e

14.1 Terminology . . . . . . . . . . .
14.2 Fault Prevention . . . . . . . .
14.3 Fault Toleran e . . . . . . . . .
14.3.1 Redundan y . . . . . . .
14.4 When Re overy is Undesirable

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

77

77
78
78
78
81
81

85

85
85
88
88
88
88
89
89
89

91

91
93
93
94
95
96
99
100

103

103
103
107
107

109

109
109
109
113
113
114
114

115

115
116
116
116
122

viii

CONTENTS

14.5 Resour es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
14.6 Exer ises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

Index

125

Glossary

129

Chapter 1

Introdu tion to Erlang
This is a `Qui k Start' hapter. It does not over Erlang in detail, instead it
fo uses on getting the user going in the language as qui kly as possible so that
the user an try out the material in subsequent hapters.
1.1

Programming Environment

Like Java, the most generally available implementation of Erlang is interpreted.
Erlang ode is ompiled into a byte ode whi h is interpreted. This allows the
ode to be easily transported between systems. Unlike Java, Erlang provides an
additional environment whi h allows the programmer to dire tly intera t with
the fun tions in their ode. This environment, known as the Erlang Shell, is
des ribed in this se tion. The ability to dire tly intera t with fun tions is a
powerful and very useful feature of Erlang.

1.1.1 Starting and Leaving the Erlang Shell
The Erlang shell is invoked from the ommand line using the erl ommand (see
gure 1.1). The shell an be exited by typing ontrol-g and then q.
% erl
Erlang (JAM) emulator version 4.3.1
Eshell V4.3.1 (abort with ^G)
1>

Figure 1.1: Starting the Erlang Shell

1.1.2 Fun tions Provided by the Shell
The shell interprets user input as fragments of Erlang ode. The shell allows
variables to be assigned and fun tions to be alled just as if the a tions took
pla e inside a ompiled Erlang program. The only di eren es between the shell
and a program are that the shell does not allow the user to de ne their own
fun tions and allows bindings to be removed.
The shell provides some on line help. It an be a essed by typing
1

2

CHAPTER 1.

INTRODUCTION TO ERLANG

help().

at the shell prompt. Shell internal ommands an be a essed just by typing
the fun tion name with its arguments in bra kets. Commands in modules are
a essed by prefa ing the fun tion name with the module name and a olon.
The ompiler fun tion is in the module and its use is shown in se tion 1.1.3.

1.1.3 Compiling and Running Programs
The rst example is a Ti -Ta -Toe game. The program le is alled ttt.erl . To
ompile the program, invoke Erlang and issue the ommand : (ttt). and to
run it use the ommand ttt:init(). Figure 1.2 shows the ompilation and gure
1.3 shows a game in progress.
% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> : (ttt).
{ok,ttt}
2> ttt:init().

Figure 1.2: Compiling and Running Ti -Ta -Toe

1.1.4 Starting Additional Shells
The run time environment whi h supports the shell an be invoked by pressing
ontrol-g. The environment provides a set of ommands whi h allow the user to
reate, kill, and onne t to many pro esses. Figure 1.4 illustrates a essing the
environment, its help information, and reating and swit hing between shells.
1.2

Anatomy of An Erlang Program

An Erlang program onsists of a set of fun tions whi h may be olle ted into
modules. A short program that ounts the number of lines and hara ters in a
le will be used as an example. The ode for the le nt program is shown in
gure 1.5. Some sample output is shown in gure 1.6.
Some interesting features of the program: 

An Erlang module is a devi e for olle ting together fun tions. Modules
are also the unit of ompilation. Thus a le whi h is to be ompiled must
ontain a module de laration (line 1 of gure 1.5. 

The visibility of fun tions are ontrolled through the export de laration
(line 2). The only fun tions in the module that an be seen by ode outside
the module are those listed in the export de laration. It is important to
note that fun tions have an arity equivalent to the number of arguments
of the fun tion. The fun tion name and the number of arguments taken
by the fun tion uniquely identify the fun tion.

1.2.

ANATOMY OF AN ERLANG PROGRAM

Figure 1.3: Ti -Ta -Toe in A tion

3

4

CHAPTER 1.

INTRODUCTION TO ERLANG

% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> h().
ok
2>^G
User swit h ommand
--> h
[nn℄ - onne t to job
i [nn℄ - interrupt job
k [nn℄ - kill job
j
- list all jobs
s
- start lo al shell
r [node℄ - start remote shell
q
- quit erlang
? | h
- this message
--> s
--> j
1 {}
2 {shell,start,[℄}
3* {shell,start,[℄}
-->
Eshell V4.5.3 (abort with ^G)
1>^G
User swit h ommand
--> 2
2>^G
User swit h ommand
--> 3
1>

Figure 1.4: A essing the Environment

1.2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

ANATOMY OF AN ERLANG PROGRAM

-module(file nt).
-export([file nt/1℄).
% A ept a filename and attempt to open the file
file nt(FileName) ->
{Status, Data} = file:open(FileName, [read℄),
if
Status == error ->
io:format("Unable to open file ~w be ause ~w~n",
[FileName, Data℄);
true ->
f (FileName, Data, {0,0})
end.
% ount hara ters and lines, return tuple
f (FN, Fd, {Chars, Lines}) ->
C = file:read(Fd, 1),
if
C == eof ->
{Chars, Lines};
true ->
{Result, Data} = C,
if
Result == error ->
io:format("Unable to read file ~w be ause ~w~n",
[FN, Data℄);
true ->
if
Data == "\n" ->
f (FN, Fd, {Chars+1, Lines+1});
true ->
f (FN, Fd, {Chars+1, Lines})
end
end
end.

Figure 1.5: File nt Sour e Code
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> : (file nt).
{ok,file nt}
2> file nt:file nt('file nt.erl').
{1006,37}
3>

Figure 1.6: Sample output from le nt

5

6

CHAPTER 1.

INTRODUCTION TO ERLANG   

Comments are pre eded with a per ent sign (lines 4 and 16).  

Re ursion is used to perform any repeating a tions (lines 32 and 34).

1.3

Two fun tions are de ned: le nt (lines 6{14) and f (lines 18{37).
Variables are assigned to exa tly on e and start with apital letters.
(lines 7, 19, and 24)
Fun tions in other modules are a essed by pre xing the name of the
module and a olon to the name of the fun tion (lines 7, 10, 19, and 28).
Fa torial: The Classi Re ursion Example

This se tion provides the lassi al explanation of the fa torial fun tion. It is
in luded to provide a link ba k to the mathemati al basis of re ursion. The fa torial fun tion is one of simplest the most used examples of a re ursive fun tion.
Card games and games of han e were signi ant driving for e in the development of probability. Questions similar to the following are not un ommon:
If you were presented with ve playing ards labeled `A' to `5' in
how many ways an you arrange those ards?

The lassi answer is: you have 5 hoi es for the rst ard, then 4 hoi es
for the se ond ard and so on until you have 1 hoi e for the nal ard. Giving
5  4  3  2  1 = 120 hoi es.
This answer an be generalised to any number of starting ards and the generalisation is known as the fa torial fun tion. It an be written as a re urren e
relationship: 

if x < 1
1)! otherwise
The Erlang fun tion fa t in gure 1.7 implements the re urren e relationship.
!=

x

1.4

1

x 

(

x

Anatomy of a Fun tion

The fa torial fun tion in gure 1.7 illustrates a number of interesting aspe ts of
the Erlang programming language: 

Fun tions are omposed of fun tion heads (lines 4 and 6) and fun tion
bodies (lines 5 and 7)

1.5.

1
2
3
4
5
6
7

7

RESOURCES

-module(fa tprg).
-export([fa t/1℄).
fa t(0) ->
1;
fa t(N) ->
N * fa t(N-1).

Figure 1.7: The fa torial fun tion: fa t 

Fun tions are omposed of lauses (lines 4{5 and lines 6{7). A lause is
omposed of a fun tion head and a fun tion body. The lauses of a fun tion
are separated by semi olons (line 5). The nal lause of a fun tion ends
in a full-stop (line 7). 

When a fun tion exe utes ea h of the fun tion heads is tested in turn. The
rst fun tion head whi h mat hes the argument the fun tion was invoked
with has its body exe uted. If no fun tion head mat hes an error o urs.
In the example line 6 is only exe uted when fa t is alled with an argument
of 0 . 

The arguments in the fun tion head are known as a pattern and the pro ess
of sele ting the fun tion head is known as pattern mat hing.

1.5

Resour es

The ode les mentioned in this hapter are:
ttt.erl
le nt.erl
fa tprg.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/erlintro.
1.6

Exer ises

1. Extend the le nt program to ount full-stops in les.
2. The algorithm used in the Ti -Ta -Toe game for automati play has no
insight into the game. Rewrite the play fun tion to play better. Hint: use
Erlang's pattern mat hing fa ilities to mat h grid positions and hard- ode
the rules for winning play.

8

CHAPTER 1.

INTRODUCTION TO ERLANG

Chapter 2

Fundamentals
This hapter des ribes the fundamental parts of the Erlang programming language in luding: basi and ompound data types, variables, fun tions, guards,
and modules.
2.1

Data Types

Nouns, verbs, and adje tives in languages like English and Swedish are olle tions of words whi h perform parti ular roles in the language. These roles
restri t the words to be used in a parti ular ontext and in a parti ular way.
The types and subtypes of words and arrangements of words in language are
sometimes alled the `parts of the language'. Programming languages also have
parts. In parti ular, the data a program works on is divided into a number of
di erent types. Normally there are onstants asso iated with this data.
Erlang supports 5 simple data types: 

Integer - a positive or negative number with no fra tional part (ie. no
de imal point)    

Float - a number with a fra tional part (ie. no de imal point)
Atom - a onstant name
Pid - a pro ess identi er
Referen e - a unique value that an be opied or passed but annot be
generated again

Two ompound data types are supported in Erlang  

Tuple - a xed length olle tion of elements
List - a variable length olle tion of element

A term is a value made from any of the above data types
9

10

CHAPTER 2.

FUNDAMENTALS

2.1.1 Integers
The Erlang programming language requires that integers have at least 24 bits
pre ision. This means that any number between 224 1 and 224 1 must be
representable as an integer. There are several ways of writing integer onstants
some examples are illustrated below:
16777215
16777215
$A
2#101
16#1A
0
In order, the examples are: the largest integer guaranteed to be present
in Erlang (some implementations may o er larger values); the smallest integer
guaranteed to be present in Erlang (some implementations may o er smaller values); the integer orresponding to the hara ter onstant `A' (integer value 65);
the integer orresponding to `1012 ' (integer value 5); the integer orresponding
to `1A16 ' (integer value 26); and 0.
The examples introdu ed 2 Erlang spe i notations. The `$' and the `#'.
The `$' returns the position of the hara ter following it in the ASCII hara ter set:
$ har
The `#' allows integers in the bases 2 : : : 16 to be spe i ed using the notation:

base#value

2.1.2 Floats
Erlang uses the onventional notation for oating point numbers. Some examples are:
16:0
16:22
1:8e2
0:36e
1:0e3
1:0e6

2

In order the examples are: 16:0; 16:22; 180:0; 3:6  10 3 ; 1000:0; and
1:0  106 .

2.1.3 Numbers
Floats and integers an be ombined into arithmeti expressions. Table 2.1 is a
table of operators used for arithmeti .

2.1.

11

DATA TYPES

Op
+X

Des ription
+X

X
X 

X
Y

X 

Y

( oating point division)
(integer division)
integer remainder of X / Y
bitwise and of X and Y
X +Y

X= Y

X= Y

X

X= Y

div Y
X rem Y
X band Y
X +Y
X
X
X
X
X

Y

bor Y
bxor Y
bsl Y
bsr Y

X

Y

bitwise or of X and Y
bitwise xor of X and Y
arithmeti shift left of X by Y bits
shift right of X by Y bits

Table 2.1: Arithmeti Operations

2.1.4 Atoms
An atom is a onstant name. The value of an atom is its name. Two atoms are
equivalent when they are spelt identi ally. Atom onstants either begin with
a lower ase letter and are delimited by white spa e; or an atom is quoted in
single quotes (` ' ').
The following are atoms:
start
begin here
'This is an atom'
'Fred'
Atoms de ned using single quotes may in lude non-printing and spe ial hara ters. Table 2.2 ontains sequen es that an be in luded in a quoted atom to
represent spe ial hara ters.
Some examples of quoted atoms ontaining spe ial hara ters are:
'hello, worldnn'
' rst linennse ond linenn'
'1nt2'
Long quoted atoms an be split a ross lines by ending the line with a ba kslash hara ter ('n').
'this is a long atom \
ontinued on the next line'

2.1.5 Pids
The programming environment that supports Erlang is designed to run many
Erlang programs in parallel. Ea h program operates independently to other
programs: parameters and memory are not shared between Erlang programs.

12

CHAPTER 2.

Char
nb
nd
ne
nf
nn
nr
nt
nv

nn
n^A . . . n^Z
n'
n"
nOOO

FUNDAMENTALS

Meaning
Ba kspa e
Delete
Es ape
Formfeed
Newline
Carriage return
Tab
Verti al tab
Ba kslash
Control A (0) to Control Z (26)
Quote
Double Quote
Chara ter with o tal value OOO

Table 2.2: Quoted Atom Conventions
This makes ea h thread of exe ution in the Erlang programming environment
a pro ess. A Pro ess Identi er (Pid) is a unique name assigned to a pro ess.
Pids are used for ommuni ating between pro esses and to identify pro esses
to the programming environment for operations whi h a e t the operation of a
pro ess { for example reating, destroying and hanging the s heduling priority
of pro esses.

2.1.6 Referen es
The Erlang run time environment provides a fun tion whi h returns a value
whi h is unique within all running Erlang environments. This value is alled
a referen e. Note that although no two referen es an be generated whi h are
identi al among running systems, an Erlang environment whi h has been failed
and is then restarted an produ e referen es whi h were previously produ ed by
the failed environment.
Unique values an prove useful as tokens in on urrent systems.

2.1.7 Tuples
Tuples are data stru tures whi h are used to store a xed number of items.
They are written as a a group of omma separated terms, surrounded by the
urly bra kets.
Examples of tuples are:

f1,2,3g
ffred,20.0,3g
f15,' fteen'g
f3,fa,b, gg
f3,[a,b, ℄g

The items that ompose a tuple are alled elements. The elements are identi ed by their position in the tuple and may be extra ted using pattern mat hing.

2.1.

DATA TYPES

13

An example is shown in gure 2.1.
% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> T = {1,2,3}.
{1,2,3}
2> {A,B,C} = T.
{1,2,3}
3> A.
1
4> B.
2
5> C.
3
6>

Figure 2.1: Manipulating a Tuple in the Erlang Shell
The size of a tuple is equivalent to the number of elements in the tuple.

2.1.8 Lists
The list data stru ture does not have a predetermined size. The Erlang programming language de nes a number of operators and fun tions that allow new
lists to be reated from an existing list whi h either have more elements or fewer
elements than the original list.
Lists are written as a a group of omma separated terms, surrounded by the
square bra kets.
Examples of lists are:
[1,2,3℄
[fred,20.0,3℄
[15,' fteen'℄
[3,[a,b, ℄℄
[fa,bg; fa,b, g℄
[℄
Erlang has a spe ial notation for generating lists of hara ters easily. A
string of hara ters en losed in double quotation marks is onverted to a list
of integers representing the hara ters. The onventions used for quoted atoms
gure 2.2 also apply. An example of this spe ial notation is shown in gure 2.2.
The verti al separator (j) is used in the list notation to separate the spe i ed
head part of a list from the remainder of the list. Some examples of the use of
this notation are shown in gure 2.3.
The majority of Erlang fun tions are written to manipulate and return
proper or well formed lists. Proper or well formed lists have an empty
list ([℄) as their last element.
Some useful fun tions that operate on lists are found in table 2.3.

14

CHAPTER 2.

FUNDAMENTALS

% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> A = "hello".
"hello"
2> B = [ a | A℄.
[a,104,101,108,108,111℄
3> [ X | Y ℄ = B.
[a,104,101,108,108,111℄
4> X.
a
5> Y.
"hello"
6> C = [ $a | A ℄.
"ahello"
7> hd(C).
97
8> $a.
97
9>

Figure 2.2: Manipulating a String / List of Chara ters in the Erlang Shell

% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> Z = [a,b, ,d,e,f℄.
[a,b, ,d,e,f℄
2> [A, B | R℄ = Z.
[a,b, ,d,e,f℄
3> A.
a
4> B.
b
5> R.
[ ,d,e,f℄
6> X = [A, B | R℄.
[a,b, ,d,e,f℄
7> X.
[a,b, ,d,e,f℄
8>

Figure 2.3: Manipulating a List Using j in the Erlang Shell

2.2.

15

VARIABLES

Fun
atom to list(X)
oat to list(X)
integer to list(X)
list to atom(X)
list to oat(X)
list to integer(X)
hd(L)
tl(L)
length(L)

Des ription
return the list of ASCII hara ters
that form the atom X
return the list of ASCII hara ters
that represent the value of the oat X
return the list of ASCII hara ters
that represent the value of the integer X
return an atom omposed of the hara ters
formed from the list of ASCII hara ters X
return a oat omposed of the hara ters
formed from the list of ASCII hara ters X
return an integer omposed of the hara ters
formed from the list of ASCII hara ters X
The head { rst element { of the list L
The tail { last element { of the list L
The number of elements in the list L

Table 2.3: Sele ted List Fun tions
2.2

Variables

Erlang's variables behave di erently to variables in pro edural languages like C,
Ada and Java. Erlang's variables have the following properties: 

The s ope (region of the program in whi h a variable an be a essed) of
a variable extends from its rst appearan e in a lause through to the end
of the lause in an Erlang fun tion. 

The ontents of an Erlang variable persist from assignment until the end
of the lause. 

Erlang variables may be assigned to (bound) exa tly on e. 

It is an error to a ess an unbound Erlang variable. 

Erlang variables are not typed. Any term an be bound to a variable.

The property of allowing a variable to bound exa tly on e is known as single

assignment.

One way of al ulating elementary fun tions su h as exp (ex ) and sine is to
use a Taylor Series. The ode in gure 2.4 illustrates how these fun tions may
be implemented. This ode an also be used to show the s ope of variables.
The fun tion sin whi h takes 4 arguments is omposed of two lauses (lines 30
{ 37) and (lines 38 { 45). Ea h of these lauses has the variables Z , N , Epsilon ,
and R . Although the variables have the same names in the two fun tions, the
variables are in fa t di erent. Furthermore, the ontents of these variables an
only be a essed within the lause where they have been de ned.

16

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

CHAPTER 2.

-module(tayser).
-export([exp/1, sin/1℄).
epsilon() ->
1.0e-8.
fa t(0) ->
1;
fa t(N) ->
N * fa t(N-1).
taylorterm(Z, N) ->
math:pow(Z, N) / fa t(N).
exp(Z) ->
exp(Z, 0, epsilon()).
exp(Z, N, Epsilon) ->
R = taylorterm(Z, N),
if
R < Epsilon ->
0;
true ->
R + exp(Z, N+1, Epsilon)
end.
sin(Z) ->
sin(Z, 0, 1, epsilon()).
sin(Z, N, 1, Epsilon) ->
R = taylorterm(Z, (2*N)+1),
if
R < Epsilon ->
0;
true ->
R + sin(Z, N+1, -1, Epsilon)
end;
sin(Z, N, -1, Epsilon) ->
R = taylorterm(Z, (2*N)+1),
if
R < Epsilon ->
0;
true ->
-R + sin(Z, N+1, 1, Epsilon)
end.

Figure 2.4: Tayser Sour e Code

FUNDAMENTALS

2.3.

2.3

17

MEMORY MANAGEMENT

Memory Management

Languages like C and C++ support fun tions that expli itly allo ate and deallo ate memory (C provides many fun tions in luding allo a, mallo , allo and
free; C++ provides new and delete). Erlang does not have expli it memory
management, freeing the programmer from having to allo ate and deallo ate
memory. Instead the language reates spa e to hold the ontents of a variable when ne essary and automati ally frees the allo ated spa e when it an no
longer be referen ed. The pro ess of freeing the allo ated memory is sometimes
alled garbage olle tion.
2.4

Fun tions

In mathemati s a fun tion des ribes a relationship between its inputs and its
outputs. The key hara teristi of this relationship is that if the same ombination of inputs is supplied then the same output is produ ed ea h and every
time the fun tion is used. This fun tional relationship is often illustrated using
a diagram similar to gure 2.5. Fun tions are sometimes said to have a many
to 1 relationship.

Input Set

Function
many

:

Output Set
1

Figure 2.5: A fun tion
The property of always getting the same result regardless of when a fun tion
is used is highly desirable. This means that a fun tion that has been tested in
one environment an be used in any other environment without worrying about
the environment a e ting the fun tion. Of ourse the new environment may
provide inputs to the fun tion that were not present in the test environment,
and hen e dis over a aw in the fun tion. However, after xing the problem,
the xed fun tion should be operable in both environments. In general, Erlang
fun tions do not intera t with their environment, ex ept through their input
parameters, and hen e exhibit this desirable property.

18
1
2
3
4
5
6
7

CHAPTER 2.

FUNDAMENTALS

-module(fa tprg2).
-export([fa t/1℄).
fa t(N) when N > 0 ->
N * fa t(N-1);
fa t(N) when N == 0 ->
1.

Figure 2.6: The fa torial fun tion: fa t
A fun tion whi h a e ts or intera ts with its environment is said to have side
e e ts. Very few fun tions in Erlang have side e e ts. The parts of Erlang whi h
exhibit side e e ts in lude: Input / Output operations, pro ess di tionaries, and
message passing. These lasses of operation will be dis ussed later.
As noted earlier (see se tion 1.4), Erlang fun tions are omposed of lauses
whi h are sele ted for exe ution by pattern mat hing the head of lause. On e
a lause is sele ted it is exe uted until it returns a value. This value is returned
to the alling fun tion. The lauses of a fun tion are separated by semi olons
and the last lause of a fun tion ends in a full-stop.
2.5

Guards

In addition to mat hing patterns, the head of a lause an be augmented with
a guard lause. Figure 2.6 shows the fa torial fun tion ( gure 1.7) rewritten to
use a guard lause. Guard lauses are also used in onditional expressions and
message re eption.
Some fun tions are allowed to be used in guards (see table 2.4). Table 2.5
shows a table of operations permitted in guards. Guard lauses an be ombined
using a logi al-and operator by separating the lauses with ommas.
Guard
atom(X)
onstant(X)
oat(X)
integer(X)
list(X)
number(X)
pid(X)
port(X)
referen e (X)
tuple (X)

Test
X is an atom
X is not a list or tuple
X is a oat
X is an integer
X is a list
X is an integer or a oat
X is a pro ess identi er
X is a port
X is a referen e
X is a tuple

The following fun tions are also permitted: element/2, oat/1, hd/1, length/1,
round/1, self/1, size/1, trun /1, tl/1
Table 2.4: Guard Tests
The ot program demonstrates the aspe ts of guards dis ussed. The sour e
ode is shown in gure 2.7 and a sample run is shown in gure 2.8. The ot

2.6.

19

MODULES

OP
X > Y
X < Y

=< Y
=Y
X == Y
X= = Y
X =:= Y
X = = = Y
X

X >

Des ription
X greater than Y
X less than Y
X less than or equal to Y
X greater than or equal to Y
X equal to Y
X not equal to Y
X exa tly equal to Y (no type onv)
X not exa tly equal to Y (no type onv)

Table 2.5: Guard Operations
program determines the type of its argument and reports it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

-module(ot).
-export([ot/1℄).
ot(X) when integer(X), X > 0 ->
'positive natural';
ot(X) when integer(X), X < 0 ->
'negative integer';
ot(X) when integer(X) ->
integer;
ot(X) when float(X) ->
float;
ot(X) when list(X) ->
list;
ot(X) when tuple(X) ->
tuple;
ot(X) when atom(X) ->
atom.

Figure 2.7: ot.erl

2.6

Modules

Modules are a me hanism for olle ting fun tions together in Erlang. No storage
is asso iated with a module, nor are any pro esses asso iated with a module.
The module is the unit of ode loading. Erlang o ers a fa ility for dynami ally
repla ing ode while a system is running. When this o urs a whole module is
imported into the system to repla e a previously loaded module.
A module begins with a number of de larations whi h are followed by the
fun tions of the module. The Wobbly Invaders program ( gure 2.9 and gure
2.10) will be used to illustrate the de larations (these de larations are sometimes
known as attributes).
The module de laration on line 1 identi es the module name. Note: the

20

CHAPTER 2.

FUNDAMENTALS

% erl
Erlang (JAM) emulator version 4.6
Eshell V4.6 (abort with ^G)
1> ot:ot(1).
'positive natural'
2> ot:ot(0).
integer
3> ot:ot(-1).
'negative integer'
4> ot:ot({1}).
tuple
5> ot:ot([1,2,3℄).
list
6>

Figure 2.8: Output from using ot
le ontaining the module must be named with the module name suÆxed with
a .erl . In this ase the module wi is stored in the le wi.erl . The import
de laration on line 2 allows the reate and on g fun tions ontained in the gs
module to be a essed without pre xing them with their module names. The use
of these fun tions an be ompared with their use in the Ti -Ta -Toe program
in hapter 1. The export de laration makes fun tions ontained in this module
available to other modules. If a fun tion is not exported it is ina essible to
fun tions outside its own module.
Fun tions in other modules an be a essed in 2 ways: 

Importing the fun tion allows the fun tion to be alled without mentioning
the module name. Eg:
start() 

A fully quali ed fun tion name in ludes the module name a olon and the
fun tion name. Eg:
gs:start()

If a module ontains a fun tion with the same name as an imported fun tion,
fully quali ed names should be used to a ess the fun tion in the other module.
A fully quali ed fun tion name is required to a ess two fun tions with the same
name and number of arguments that are exported from two di erent modules.
2.7

Built In Fun tions

Erlang de nes a spe ial lass of fun tions known as Built In Funtions or BIFs.
In an interpreted environment these fun tions are built in to the interpreter.
BIFs are members of the module erlang .

2.7.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

BUILT IN FUNCTIONS

-module(wi).
-import(gs, [ reate/3, onfig/2℄).
-export([init/0℄).
init() ->
S = gs:start(),
Win = reate(window, S, [{width, 200}, {height, 200},
{title, 'Atta k of the Wobbly Invaders'}℄),
Canvas = reate( anvas, Win, [{width, 200}, {height, 200},
{bg, white}℄),
onfig(Win, {map, true}),
loop(Canvas, 0, 0, 1).
loop(C, X, Y, P) ->
drawwi(C, X, Y, P),
re eive
{gs, Id, destroy, Data, Arg} ->
bye
after 500 ->
erasewi(C, X, Y),
if
Y == 200 ->
bye;
X == 200 ->
loop(C, 0, Y+20, -P);
true ->
loop(C, X+20, Y, -P)
end
end.
drawwi(C, X, Y, 1) ->
reate(image,C,[{load_gif,"thing1.gif"}, { oords, [{X,Y}℄}℄);
drawwi(C, X, Y, -1) ->
reate(image,C,[{load_gif,"thing2.gif"}, { oords, [{X,Y}℄}℄).
erasewi(C, X, Y) ->
reate(re tangle,C,[{ oords,[{X,Y},{X+20,Y+20}℄},
{fg, white}, {fill,white}℄).

Figure 2.9: Wobbly Invaders Sour e Code (wi.erl )

21

22

CHAPTER 2.

FUNDAMENTALS

Figure 2.10: The Wobbly Invaders in A tion
2.8

Resour es

The ode les mentioned in this hapter are:
tayser.erl
fa tprg2.erl
ot.erl
wi.erl
thing1.gif
thing2.gif
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/fund.
2.9

Exer ises

1. Alter the tayser program so that all variable names are not reused in
di erent lauses. Test the program to onvin e yourself that the old and
new versions of the program work identi ally.
2. Alter the Wobbly Invaders program to use fully quali ed fun tions instead
of the import dire tive.

Chapter 3

Writing Fun tions
This hapter initially looks at the di eren es between Erlang and other languages. It then pro eeds to des ribe how fun tions an be lassi ed and using
the lassi ation illustrates how fun tions an be written in the language.
3.1

Pro edural versus De larative

Languages like C, Pas al, C++, Ada, Java, Cobol and Fortran are pro edural
languages. In these languages the programmer des ribes in detail how to solve
a problem. Erlang is a de larative language. In a de larative language, the
programmer des ribes what the problem is. The di eren e between the two
styles of programming is best seen by example. Two programs have been written
to solve the following problem:
The problem: A person takes a mortgage of $10000 at 6.15% per
annum and makes monthly payments of $200. How many months
does it take to lear the debt?
The solution in Fortran 77 is given in gure 3.1. This solution is typi al
for other pro edural languages as it uses a loop to al ulate the outstanding
amount of the loan while the loan is greater than zero dollars. The pro ess of
solving the problem is stated more learly than the obje tives of the program.
The solution in Erlang is given in gure 3.2. The Erlang solution di ers
from the Fortran solution in many ways. The most striking di eren e is in the
nt fun tion. The rst lause of the nt fun tion states that a solution has been
found when the outstanding amount (Outs ) has dropped to or below zero. If a
solution has not been found the se ond lause of the fun tion des ribes where
to look for the next result. Naturally there remains a pro edural element to the
se ond lause { it des ribes how to al ulate the next step { but the emphasis is
on the what of the problem. Another signi ant di eren e between the Erlang
solution and the Fortran solution is the la k of an iteration onstru t in Erlang.
Erlang employs re ursion instead. The absen e of iteration en ourages de larative programming pra ti es. Guards and pattern mat hing are two methods of
learly des ribing aspe ts of the problem.
The output from the two programs is shown in gure 3.3.
23

24

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

CHAPTER 3.

WRITING FUNCTIONS

PROGRAM MORT
C
C
C
C
C
C

Cal ulate the length of a morgage in months
OUTS - outstanding amount
INTR - interest harged
RATE - monthly interest rate
N - number of months
REPAY - Repayment
REAL OUTS, INTR, RATE, REPAY
INTEGER N

C Initial values
OUTS = 10000.0
RATE = (6.15 / 100.0) / 12.0
REPAY = 200.0
N = 0
10

INTR = OUTS *
OUTS = OUTS +
OUTS = OUTS N = N + 1
IF (OUTS .GT.

20
100

RATE
INTR
REPAY
0.0) GO TO 10

WRITE (6, FMT=100) N
FORMAT (I5)
CLOSE(6)
STOP
END

Figure 3.1: Solution to Mortgage problem in Fortran 77: mort.f

3.1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

PROCEDURAL VERSUS DECLARATIVE

-module(mort).
-export([mort/4℄).
%
%
%
%

Cal ulate the number of repayments required to pay
a mortgage of Amt repaid at NumRep payments of Repay per
year with interest taken NumRep times using an annual
interest rate of Rate

mort(Amt, Rate, NumRep, Repay) ->
AddRate = Rate / 100.0 / NumRep,
nt(Amt, Repay, AddRate, 0).
nt(Outs, Sub, AddRate, N) when Outs =< 0.0 ->
N;
nt(Outs, Sub, AddRate, N) ->
Add = Outs * AddRate,
nt(Outs - Sub + Add, Sub, AddRate, N+1).

Figure 3.2: Solution to Mortgage problem in Erlang: mort.erl

% mort
58
% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> mort:mort(10000.0, 6.15, 12, 200.0).
58

Figure 3.3: The output of mort.f and mort.erl

25

26

CHAPTER 3.

WRITING FUNCTIONS

Both the Fortran solution and the Erlang solution presented have used a
simulation approa h to solving the mortgage problem. With deeper insight into
the problem a more dire t mathemati al solution an be reated. This solution
is shown in gure 3.4.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

-module(mort2).
-export([mort/4℄).
-import(math, [log/1℄).
%
%
%
%

Cal ulate the number of repayments required to pay
a mortgage of Amt repaid at NumRep payments of Repay per
year with interest taken NumRep times using an annual
interest rate of Rate

mort(Amt, Rate, NumRep, Repay) ->
AddRate = Rate / 100.0 / NumRep,
repayments(Amt, AddRate, Repay).
repayments(Loan, Rate, Payment)
when Loan >= 0, Rate == 0, Payment > Loan*Rate ->
eiling(Loan/Payment);
repayments(Loan, Rate, Payment)
when Loan >= 0, Rate > 0, Payment > Loan*Rate ->
eiling(-log(1.0 - Rate*Loan/Payment)/log(1.0 + Rate)).
eiling(X) ->
N = trun (X),
if
N < X -> N+1;
N >= X -> N
end.

Figure 3.4: A More Insightful Solution to Mortgage problem in Erlang:
mort2.erl

3.2

A Taxonomy of Fun tions

Fun tions an be olle ted into groups based on the relation between the volume
of their input data to their output data. One set of groups olle ts fun tions
into the ategories:    

Transformation
Redu tion
Constru tion
Redu tion and Constru tion

3.2.

A TAXONOMY OF FUNCTIONS

27

In general all fun tions transform their input data into their output data, however, in this lassi ation the volume of data is not hanged, it is merely onverted into another form. Constru tive fun tions make larger data stru tures
from their input data and redu ing fun tions ondense their input data into a
smaller data stru ture. These lassi ations of fun tions an be demonstrated
with both tuples and lists, although it is somewhat easier to write examples
using lists.

3.2.1 Transformation
The sine fun tion math:sin in the Erlang math library is a simple example of a
transformation.

3.2.2 Redu tion
A lassi example of a fun tion that redu es its inputs is the len fun tion (see
gure 3.5) whi h operates similarly to the length fun tion provided by Erlang.
This fun tion a epts a list and returns the number of elements in the list.
1
2
3
4
5
6
7

-module(len).
-export([len/1℄).
len([℄) ->
0;
len([H | T℄) ->
1 + len(T).

Figure 3.5: An implementation of length in Erlang: len.erl
The redu tionist approa h taken here stems from knowing what the zero
length ase looks like; and knowing that a list with one less element an be
made by taking the tail of the input list and the urrent list length is one more
than the tail of the list. The list is redu ed until it is empty then ea h stage
adds one to the value returned by its redu ed list. The top level fun tion returns
the length of the list. Figure 3.6 shows a modi ed program and the output at
ea h stage.

3.2.3 Constru tion
A fun tion that inserts a node in a Binary Sear h Tree (BST) is an example of
a onstru tive fun tion. Fun tion insert from the bst module (see gure 3.7)
demonstrates the onstru tion of a tree.
As with redu tion, at least one base ase needs to be known and indu tion is
used to onstru t other ases. In the BST example the base ase is the onstru tion of a single node tree from an empty tree. All other ases are onstru ted
by lo ating a suitable nil leaf node, repla ing it with a newly onstru ted node
and then opying the remainder of the tree.
Redu tion type fun tions have a fairly obvious point at whi h they are ompleted, when they have exhausted the resour e they are redu ing. Constru tion

28

1
2
3
4
5
6
7
8
9
10
11

CHAPTER 3.

WRITING FUNCTIONS

-module(lens).
-export([len/1℄).
len([℄) ->
0;
len(X) ->
[H|T℄ = X,
io:format("~w ~w~n", [H, T℄ ),
LenT = len(T),
io:format("~w ~w ~w ~w~n", [1 + LenT, H, LenT, T℄ ),
1 + LenT.

% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> (lens).
{ok,lens}
2> lens:len([a,b, ,d,e,f,g℄).
a [b, ,d,e,f,g℄
b [ ,d,e,f,g℄
[d,e,f,g℄
d [e,f,g℄
e [f,g℄
f [g℄
g [℄
1 g 0 [℄
2 f 1 [g℄
3 e 2 [f,g℄
4 d 3 [e,f,g℄
5 4 [d,e,f,g℄
6 b 5 [ ,d,e,f,g℄
7 a 6 [b, ,d,e,f,g℄
7
3>

Figure 3.6: len in A tion: lens.erl

3.2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

A TAXONOMY OF FUNCTIONS

-module(bst).
-export([insert/2, prefix/1, list_to_bst/1℄).
% A BST is omposed of nodes {Left, Item, Right}
% an empty tree is denoted by a nil.
% insert(Tree, Item) - Insert an item into a tree
insert(nil, Item) ->
{nil, Item, nil};
insert({Left, Val, Right}, Item) ->
if
Item =< Val ->
{insert(Left, Item), Val, Right};
Item > Val ->
{Left, Val, insert(Right, Item)}
end.
% prefix(Tree) - Prefix Sear h
prefix(nil) ->
nil;
prefix({Left, Val, Right}) ->
LR = prefix(Left),
RR = prefix(Right),
if
LR =/= nil, RR =/= nil ->
lists:append(LR, lists:append([Val℄, RR));
LR =/= nil ->
lists:append(LR, [Val℄);
RR =/= nil ->
lists:append([Val℄, RR);
true ->
[Val℄
end.
% list_to_bst(List) - Convert a list to a bst
list_to_bst(L) ->
list_to_bst(L, nil).
list_to_bst([℄, Tree) ->
Tree;
list_to_bst([H|T℄, Tree) ->
list_to_bst(T, insert(Tree, H)).

Figure 3.7: bst.erl

29

30

CHAPTER 3.

WRITING FUNCTIONS

type fun tions must be limited to stop onstru ting larger and larger data stru tures without limit. Several methods are available in luding the Redu tion /
Constru tion type fun tion provides one method (see se tion 3.2.4). Two other
methods will be dis ussed here: performing only N steps, and ounters.
The insert fun tion uses the performing only N steps me hanism. This
fun tion reates a tree whi h has exa tly one extra node, one step in the pro ess
of reating a tree. There is no risk of this fun tion regressing in nitely.
An example of a fun tion using a ounter is the ndupl fun tion in gure 3.8.
This fun tion reates a list of a spe i ed size with opies of a value.

1
2
3
4
5
6
7
8
9

-module(ndupl).
-export([ndupl/2℄).
% ndupl(Item, N) - make a list ontaining N Items
ndupl(_, 0) ->
[℄;
ndupl(Item, N) ->
[Item | ndupl(Item, N-1)℄.

Figure 3.8: ndupl.erl
The performing only N steps me hanism di ers from the ounter me hanism
and Redu tion / Constru tion type fun tions in that there are no ounters and
no data stru tures are redu ed.

3.2.4 Redu tion / Constru tion
The Redu tion / Constru tion me hanism uses the Redu tion me hanism to
extra t data from one data stru ture and the Constru tion me hanism to add
the element to a new data stru ture. Using redu tion ensures that the operation
is nite.
The fun tion list to bst from the bst module (see gure 3.7) redu es a list
and builds a tree.
Another example of this me hanism is the fun tion atten (see gure 3.9)
whi h takes in a list of lists and produ es a list ontaining the elements of the
list of lists but without any lists. The work is done in the fun tion l2: atten/2 .
This fun tion removes elements from its se ond argument and appends them to
its rst argument. If the head of the se ond argument is a list atten is invoked
on it and the result is appended to the rst argument. This fun tion an be
thought of as stripping the bra kets o ea h list until a single list remains and
then appending the single list to the end of an already attened list. When the
se ond argument is empty the fun tion returns the rst argument.
The output of the fun tion atten an be seen in gure 3.10.

3.2.

1
2
3
4
5
6
7
8
9
10
11
12
13

A TAXONOMY OF FUNCTIONS

-module(l2).
-export([flatten/1℄).
-import(lists,[append/2℄).
flatten(L) ->
flatten([℄, L).
flatten(L, [℄) ->
L;
flatten(L, [H|T℄) when list(H) ->
flatten(append(L, flatten(H)), T);
flatten(L, [H|T℄) ->
flatten(append(L, [H℄), T).

Figure 3.9: l2.erl

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> l2:flatten([1,2,3,[4,5,6,7℄,8,[9℄℄).
[1,2,3,4,5,6,7,8,9℄
2> l2:flatten([[1,2,3℄,[[[4℄,5℄,6℄,[℄,7℄).
[1,2,3,4,5,6,7℄
3>

Figure 3.10: The output of atten

31

32

CHAPTER 3.

3.3

WRITING FUNCTIONS

Resour es

The ode les mentioned in this hapter are:
mort.f
mort.erl
mort2.erl
len.erl
lens.erl
bst.erl
ndupl.erl
l2.erl
app.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/wrtfn.
3.4

Exer ises

1. Erlang provides a fun tion lists:append whi h joins two lists together, implement your own fun tion app that performs the append operation. (Do
NOT peek; the answer is given in gure 3.11).
2. Write a narrative des ription of how the app fun tion in gure 3.11 works.

3.4.

1
2
3
4
5
6
7

EXERCISES

-module(app).
-export([app/2℄).
app([℄, L) ->
L;
app([H|T℄, L) ->
[H | app(T, L)℄.

Figure 3.11: The append fun tion (app ) in app.erl

33

34

CHAPTER 3.

WRITING FUNCTIONS

Chapter 4

Choi es

In previous hapters sele tion of whi h pie e of ode to exe ute has generally
been made using pattern mat hing and fun tion head guards. A number of
hoi e fun tions have been mentioned and used in examples, but without detailed explanation. This hapter will introdu e the if and ase fun tions.
Care must be taken when using hoi e fun tions to ensure that the single
assignment property of variables in Erlang is not violated. Runtime errors will
be generated if an unbound variable is a essed or a bound variable is assigned
to.
The fragment of C in gure 4.1 illustrates two hoi e me hanisms present in
the C language. The if me hanism is a statement and hen e does not return
a value. The ?: me hanism is an operator and behaves like a fun tion in that
it returns a value. Languages su h as Ada, Java, and Fortran, tend to provide
statement based hoi e me hanisms. In ontrast, Erlang's hoi e me hanisms
return values.
1
2
3
4
5
6
7
8
9
10
11
12
13

int max(int a, int b)
{
if (a > b)
return a;
else
return b;
}
int min(int a, int b)
{
return a < b ? a : b;
}

Figure 4.1: max and min in C
Figure 4.2 shows the Erlang ode that implements the fun tions max and
min in Erlang.
The following se tions will dis uss the implementation of hoi e using if, ase
and fun tion heads. A fun tion that determines the orre t minimal hange to
35

36
1
2
3
4
5
6
7
8
9
10
11
12
13
14

CHAPTER 4.

CHOICES

-module(maxmin).
-export([max/2,min/2℄).
max(A,B) ->
if
end.
min(A,B) ->
if
end.

A > B -> A;
true -> B

A < B -> A;
true -> B

Figure 4.2: max and min in Erlang
be delivered by a vending ma hine will be used as an example. The ent is the
unit of urren y in Australia and the available oins are 2 dollar, 1 dollar, 50
ent, 20 ent, 10 ent, and 5 ent. As the 2 ent and 1 ent oins were withdrawn
from servi e the following additional rule applies: values are rounded to the
nearest 5 ents. This rule requires 2 and 1 ent amounts be rounded to 0, and
that 3 and 4 ent amounts be rounded to 5 ents.
4.1

If

The if onstru t onsists of a series of guards and sequen es separated by semi olons. The syntax of the if onstru t is shown below:

if

Guard1
Seq1;

> 

end

GuardN
SeqN

>

The sequen e asso iated with the rst mat hing guard is exe uted. If no
guard mat hes an error o urs. When the atom true is used as a guard it a ts
as a at h all { a at h all will mat h any pattern. Figure 4.3 ilustrates the use
of the if onstru t.
4.2

Case

The ase onstru t onsists of a series of patterns { with optional guards { and
sequen es separated by semi olons. The syntax of the ase onstru t is shown
below:

4.3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

37

FUNCTION HEADS

-module( hg1).
-export([ hange/1℄).
hange(X) ->
BaseSum = (X div 5) * 5,
Delta = X - BaseSum,
if
Delta >= 3 -> hange(BaseSum + 5, [℄);
true -> hange(BaseSum, [℄)
end.
hange(X, L) ->
if

end.

X >=
X >=
X >=
X >=
X >=
X >=
true

200 ->
100 ->
50 ->
20 ->
10 ->
5 ->
-> L

hange(X
hange(X
hange(X
hange(X
hange(X
hange(X

-

200,
100,
50,
20,
10,
5,

['2.00' | L℄);
['1.00' | L℄);
['50' | L℄);
['20' | L℄);
['10' | L℄);
['5' | L℄);

Figure 4.3: hg1.erl
ase Expr of

Pattern1 [when Guard1℄
Pattern2 [when Guard2℄ 

end

PatternN [when GuardN℄

>

Seq1;
Seq2;

>

SeqN

>

The expression { Expr { is evaluated before any of the patterns are evaluated.
The sequen e asso iated with the rst mat hing pattern to the output of Expr
is exe uted. If no pattern mat hes the result of the expression a mat h error
will o ur. The pattern ` ' is a at h all will mat h anything and an be used
to avoid the risk of a mat h error.
Figure 4.4 ilustrates the use of the ase onstru t.

4.3

Fun tion Heads

As mentioned earlier in hapter 2 the lauses of a fun tion an be sele ted for
exe ution based on the arguments ontained in the head of the lause or by
guards.
Figure 4.4 ilustrates the example problem implemented ode sele ted using
the guards present in the fun tion heads.

38

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

CHAPTER 4.

CHOICES

-module( hg2).
-export([ hange/1℄).
hange(X) ->
BaseSum = (X div 5) * 5,
Delta = X - BaseSum,
ase Delta of
3 -> Rounded = BaseSum + 5;
4 -> Rounded = BaseSum + 5;
_ -> Rounded = BaseSum
end,
hange(Rounded, [200, 100, 50, 20, 10, 5℄, [℄).
hange(X, VL, L) ->
ase {X, VL} of
{X, [℄} ->
L;
{X, [H|T℄} when X >= H ->
hange(X - H, VL, [toatom(H) | L℄);
{X, [H|T℄} ->
hange(X, T, L)
end.
toatom(X) ->
ase X of
200 -> '2.00';
100 -> '1.00';
50 -> '50';
20 -> '20';
10 -> '10';
5 -> '5'
end.

Figure 4.4: hg2.erl

4.3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

39

FUNCTION HEADS

-module( hg3).
-export([ hange/1℄).
hange(X) ->
BaseSum = (X div 5) * 5,
Delta = X - BaseSum,
hange(round(BaseSum, Delta), [℄).
round(X, Y) when Y >= 3 ->
X + 5;
round(X, Y) ->
X.
hange(X, L) when X >= 200 ->
hange(X - 200, ['2.00' | L℄);
hange(X, L) when X >= 100 ->
hange(X - 100, ['1.00' | L℄);
hange(X, L) when X >= 50 ->
hange(X - 50, ['50' | L℄);
hange(X, L) when X >= 20 ->
hange(X - 20, ['20' | L℄);
hange(X, L) when X >= 10 ->
hange(X - 10, ['10' | L℄);
hange(X, L) when X >= 5 ->
hange(X - 5, ['5' | L℄);
hange(X, L) ->
L.

Figure 4.5: hg3.erl

40

CHAPTER 4.

4.4

CHOICES

Resour es

The ode les mentioned in this hapter are:
h.
maxmin.erl
hg1.erl
hg2.erl
hg3.erl
erasto.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/ hoi e.
4.5

Exer ises

1. Eratosthenes (276 - 196 BC) a Greek astronomer developed a te hnique
for extra ting prime numbers from a set of numbers. A prime number is
only divisible by 1 and itself. His te hnique (The Sieve of Eratosthenes)
involves writing down all the numbers from 3 to some value N . He then
marked ea h number that was a multiple of 2. He then lo ated the next
unmarked number and removed all multiples of it. This pro ess is repeated
until the next unmarked number is greater than the square root of N .
Implement the Sieve of Eratosthenes in Erlang. (Hint you may want to
think about what marking means in the algorithm.)
(Do NOT peek; the answer is given in gure 4.6).
2. Examine the examples of hange in this hapter and identify whi h hoi e
me hanisms best suit the problem. Dis uss the bene ts and drawba ks of
ea h me hanism. Write an Erlang implementation whi h uses the most
appropriate hoi e me hanisms for ea h de ission point in the program.
3. Rewrite the Sieve of Eratosthenes shown in gure 4.6 using other hoi e
me hanisms.

4.5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

EXERCISES

-module(erasto).
-export([era/1℄).
era(N) ->
[1 | era(math:sqrt(N), fill(2, N))℄.
fill(L, L) ->
[L℄;
fill(L, H) when H > L ->
[L | fill(L+1, H)℄.
era(Max, L) when hd(L) =< Max ->
Prime = hd(L),
[Prime | era(Max, sieve(Prime, L))℄;
era(Max, L) ->
L.
sieve(N, [℄) ->
[℄;
sieve(N, [H|T℄) when H rem N == 0 ->
sieve(N, T);
sieve(N, [H|T℄) ->
[H | sieve(N, T)℄.

Figure 4.6: The Sieve of Eratosthenes: era in erasto.erl

41

42

CHAPTER 4.

CHOICES

Chapter 5

Pro esses and Messages
Erlang provides easy a ess to lightweight pro esses, simple but powerful InterPro esses Communi ation (IPC) me hanisms, and easy to use distributed pro essing. This hapter addresses the me hanisms whi h provide these fa ilities.

5.1

Pro esses

A pro ess is the basi unit of exe ution of an Erlang program. The name of a
pro ess or Pro ess IDenti er (PID) is used. Pro esses are re ipients of messages
and hold the running state of a thread of exe ution.
A pro ess is started in Erlang by using the spawn fun tion. The simple
form of the spawn fun tion takes a series of arguments in luding the module
name, the name of the fun tion and a list of arguments to a fun tion. The PID
of the new pro ess is returned to the alling pro ess.
The syntax of the spawn fun tion is:
pid = spawn(module , fun tion , [args : : : ℄)
pid = spawn(fmodule , fun tion g, [args : : : ℄)

Figure 5.1 shows an intera tive way of using the spawn fun tion to reate
a new shell (whi h takes over terminal IO).
In general, spawn reates a pro ess and returns immediately to the alling
pro ess. The alled pro ess is then independent of its reator.

5.1.1 Finding a Pro esses Name
Erlang pro esses an determine their Pro ess ID by alling the self fun tion.
Figures 5.2 and 5.3 illustrate the use of the spawn and self fun tions.
The result of the self fun tion is a data element alled a pid . PIDs are not
human readable, however, there is an on-s reen representation that is displayed
whenever a pid is output. Typing in this representation in the Erlang shell to
use it as a pid will fail.
43

44

CHAPTER 5.

PROCESSES AND MESSAGES

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> F = 2.
2
2> spawn(shell, start, [[℄℄).
<0.29.0>
Eshell V4.6.4 (abort with ^G)
1> F.
** exited: {{unbound,'F'},{erl_eval,expr,3}} **
2> exit().
** Terminating shell **
3> F.
2
4>

Figure 5.1: Spawning a Se ond Shell From an Erlang Shell
1
2
3
4
5
6
7
8
9
10
11
12

-module(spwslf).
-export([start/0, newfn/0℄).
start() ->
MyPid = self(),
io:format("demo: ~w~n", [MyPid℄),
NewPid = spawn(spwslf, newfn, [℄),
io:format("demo: ~w~n", [MyPid℄).
newfn() ->
MyPid = self(),
io:format("newfn: ~w~n", [MyPid℄).

Figure 5.2: Spawning and Identifying Pro esses: spwslf.erl
% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> spwslf:start().
demo: <0.20.0>
demo: <0.20.0>
newfn: <0.23.0>
ok
2>

Figure 5.3: Exer ising spwslf.erl

5.2.

45

MESSAGES

5.1.2 Pro ess Di tionary
Ea h pro ess has an asso iative store { known as the Pro ess Di tionary { that
is private to the pro ess. Use of the pro ess di tionary is dis ouraged as the
pro ess di tionary breaks aspe ts of the fun tional paradigm, and programs
whi h use it tend to be harder to modify and maintain.
The fun tions put, get, erase, and get keys are used to a ess the pro ess
di tionary.
The fun tion put adds a key value pair to the pro ess di tionary. If the key
already exists in the pro ess di tionary the key value pair in the di tionary is
repla ed and the old value is returned, otherwise the atom unde ned is returned.
The ontents of the pro ess di tionary an be returned as a set of key value tuples
by using get with no arguments. The value asso iate with a parti ular key an
be found by alling get with the key. The entire pro ess di tionary an be
deleted by alling erase with no arguments. The erased ontents of the pro ess
di tionary are returned. An individual key value pair an be erased by alling
erase with the key. If the key to be erased exists in the pro ess di tionary, the
old value is returned, otherwise the atom unde ned is returned. A list of all the
keys whi h orrespond to a value in the pro ess di tionary an be found using
the get keys fun tion with the value as the argument.
The pro ess di tionary is exer ised in gure 5.4 and the ode is shown in
gure 5.5. This example implements a simple rolodex or phone book.

5.1.3 Message Bu er
Asso iated with ea h pro ess is a logi al bu er whi h ontains all messages that
are waiting to be re eived by the pro ess. Most implementations of Erlang use
a ommon pool of bu er spa e whi h is shared by all the pro esses on a node.
5.2

Messages

Messages are sent to pro esses using the ! operator. this operator takes two
arguments the PID or a registered name and an expression:
pid ! expression
The ! operator always appears to send a message. If there is no destination
or there is no spa e to queue the message at its destination then the message is
dis arded. Erlang o ers NO guarantee of message delivery.
The result of the expression is transmitted to the pro ess named by pid . The
message is stored until the pro ess hooses to re eive it by exe uting a re eive
expression. Re eive has a similar stru ture to ase, ex ept that it operates on
the pro ess's message queue.

re eive

Message1 [when Guard1℄
Message2 [when Guard2℄ 

MessageN[when GuardN℄

after
end

TimeOut

>

A tT

>

A t1;
A t2;

>

A tN

>

46

CHAPTER 5.

PROCESSES AND MESSAGES

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> pr d t:teldir().
Enter name and phone number (blank line to end)
name phone> john 92914592
name phone> max 93442156
name phone> fred 9834231
name phone>
Operation
1) Sear h 2) Add/Change 3) List Names 4) Delete
op > 3
fred
max
john
op > 4
name > fred
9834231
op > 1
name > fred
undefined
op > 3
max
john
op > 2
Enter name and phone number (blank line to end)
name phone> jane 94514567
name phone>
op > 3
jane
max
john
op > 1
name > jane
94514567
op > 0
true
2>

0) Quit

Figure 5.4: Exer ising the Pro ess Di tionary

5.2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

47

MESSAGES

-module(pr d t).
-export([teldir/0℄).
teldir() -> getdata(), menu(), querylp().
getdata() ->
io:format("Enter name and phone number ", [℄),
io:format("(blank line to end)~n", [℄),
getlp().
getlp() ->
Line = io:get_line('name phone> '),
Lst = string:tokens(Line, " \n"),
getlp(Lst).
getlp([Name, Phone℄) ->
put(Name, Phone),
getlp();
getlp(Lst) when length(Lst) == 0 ->
true;
getlp(_) ->
io:format("Error~n"),
getlp().
menu() ->
io:format("Operation~n 1) Sear h 2) Add/Change "),
io:format("3) List Names 4) Delete
0) Quit~n", [℄).
querylp() -> querylp(io:fread('op > ', "~d")).
querylp({ok,
querylp({ok,
querylp({ok,
querylp({ok,
querylp({ok,

[0℄})
[1℄})
[2℄})
[3℄})
[4℄})

->
->
->
->
->

true;
sear h(), querylp();
getdata(), querylp();
lstname(), querylp();
delete(), querylp().

getnam() ->
Line = io:get_line('name > '),
getnam(string:tokens(Line, " \n")).
getnam([L℄) -> L;
getnam(_) -> io:format("Error~n"), getnam().
sear h() -> io:format("~s~n", [get(getnam())℄).
lstname() -> lstname(get()).
lstname([℄) -> true;
lstname([{Key, Value}|T℄) -> io:format("~s~n", [Key℄), lstname(T).
delete() -> io:format("~s~n", [erase(getnam())℄).

Figure 5.5: Code for Exer ising the Pro ess Di tionary: pr d t.erl

48

CHAPTER 5.

PROCESSES AND MESSAGES

Unbound variables in Message a t as wild ards and are bound to values
when a suitable mat h is found. If Message is an unbound variable it will
mat h any message and be bound to the ontents of the message. An unbound
variable a ts as a at h all. A tT is exe uted if TimeOut millise onds elapse
and there is no message that is mat hed by a pattern in the re eive fun tion. If
the value of TimeOut is in nity then the re eive does not time out and A tT
is not exe uted. If the value is 0 then all the messages are he ked and if none
mat h A tT is exe uted immediately.
The time order of messages from one pro ess to another is preserved and the
re eive statement sele ts the oldest message that su essfully pattern mat hes.
It is the responsibility of the pro ess to remove irrelevant or invalid messages
from its message bu er. Failure to do this an result in losing valid messages
when spa e is no longer available to store messages. Long running pro esses
usually have a at h all at some point in the program to remove messages whi h
do not mat h any pattern required by the program.
In se tion 5.1.2 the use of a pro esses di tionary was dis ouraged, the next example illustrates how the fun tionality of the pro ess di tionary an be a hieved
in an extensible manner without using the existing pro ess di tionary fun tions
dis ussed earlier.
Figure 5.6 provides an implementation of Pro ess Di tionary fun tionality
through the use of messages and pro esses. Only two fun tions are illustrated:
get and put . The program is exer ised in gure 5.7.
A pro ess re eiving a message does not know whi h pro ess sent it. Be ause
messages are anonymous, a pro ess an only reply to a message if the message
ontains the pid of the sending pro ess. The self all is used to gain a pro ess's
pid whi h an then be sent in a message so the destination pro ess an reply to
the message.
5.3

Time Delays

Erlang uses a degenerate form of re eive to generate a time delay. Figure 5.8
shows ode that implements a 10 se ond ount down.
5.4

Distribution

Distribution is almost trivially easy in Erlang. Starting a pro ess on another
node is a straight forward extension of the syntax of the spawn fun tion.
The rst task is to start a remote node with a name. This an be done in
two ways using the -sname option or the -name option.
The example in gure 5.9 shows both methods and assumes that the ma hine
the Erlang node is being started on is alled atum. astro.aus.net . The node
name in ea h ase will be mauri e .
The two methods are almost identi al with the ex eption that the latter
generates a fully quali ed name.
To start a pro ess on a remote node the node name is introdu ed into the
spawn fun tion:
pid = spawn(node , module , fun tion , [args

:::

℄)

5.4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

DISTRIBUTION

-module(d t).
-export([start/0,get/2,put/3,d t/1℄).
start() ->
spawn(d t,d t,[[℄℄).
get(Pid, Key) ->
Pid ! {get, self(), Key},
re eive
X -> X
end.
put(Pid, Key, Value) ->
Pid ! {put, self(), Key, Value},
re eive
X -> X
end.
d t(L) ->
NewL = re eive
{put, Pid, Key, Value} ->
{Code, List} = insert(L, [℄, Key, Value),
Pid ! Code,
List;
{get, Pid, Key} ->
Code = find(L, [℄, Key),
Pid ! Code,
L;
X ->
L
end,
d t(NewL).
insert([℄, N, Key, Value) ->
{undefined, [{Key, Value}|N℄};
insert([{Hkey, HVal} |T℄, N, Key, Value) when Key == Hkey ->
{HVal, lists:append(N,[{Key, Value} | T℄)};
insert([H|T℄, N, Key, Value) ->
insert(T, [H|N℄, Key, Value).
find([℄, N, Key) ->
undefined;
find([{Hkey, HVal}|T℄, N, Key) when Key == Hkey ->
HVal;
find([H|T℄, N, Key) ->
find(T, [H|N℄, Key).

Figure 5.6: Sour e ode for a Di tionary: d t.erl

49

50

CHAPTER 5.

PROCESSES AND MESSAGES

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> P = d t:start().
<0.28.0>
2> d t:put(P,fred,123).
undefined
3> d t:get(P,fred).
123
4> d t:get(P,fred).
123
5> d t:put(P,john,456).
undefined
6> d t:get(P,fred).
123
7> d t:get(P,john).
456
8> d t:put(P,john,678).
456
9> d t:get(P,john).
678
10> d t:get(P,fred).
123
11>

Figure 5.7: Exer ising d t.erl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

-module( ntdwn).
-export([start/0℄).
start() ->
ntdwn(10).
ntdwn(N) when N > 0 ->
io:format("~w~n", [N℄),
re eive
after 1000 ->
true
end,
ntdwn(N-1);
ntdwn(_) ->
io:format("ZERO~n").

Figure 5.8: Sour e ode for a Count Down: ntdwn.erl

5.5.

51

REGISTERED NAMES

atum_1% erl -sname mauri e
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
(mauri eatum)1>
atum_1% erl -name mauri e
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
(mauri eatum. astro.aus.net)1>

Figure 5.9: Starting a Distributed Node
Sending messages to a pro ess on a remote node is identi al to sending
messages to a pro ess on a lo al node.
5.5

Registered Names

All the prior examples of message sending have used expli it pids to identify
where a message is to be sent. Registering a pro ess allows a symboli name to
be asso iated with a Pro ess ID. A symboli name is parti ularly useful where
a pro ess is o ering a servi e and that is widely used as it avoids the need to
distribute the pid of that servi e to its potential users.
The fun tion register is used to asso iate a name on the lo al node with a
pid:

register(name , pid )
The asso iation an be removed using unregister:

unregister(name )
And a pid an be re overed for a name using whereis, unde ned is returned
if the name is not asso iated with a pid.

whereis(name )
Registered names on the lo al node an be used instead of a pid in the `!'
operation. Names on remote nodes an be a essed using `fName , Node g !
Message '
5.6

Resour es

The ode les mentioned in this hapter are:
spwslf.erl
pr d t.erl
d t.erl
ntdwn.erl

52

CHAPTER 5.

PROCESSES AND MESSAGES

These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/pro msg.
5.7

Exer ises

1. Modify d t.erl (see gure 5.6) to implement all the fun tions provided by
the pro ess di tionary.
2. Modify pr d t.erl to use the di tionary ode you wrote in the previous
exer ise.

Chapter 6

Meta-programming
In C it is possible to use a pointer to a fun tion to name a fun tion and evaluate
it. Figure 6.1 shows an example of where alling a fun tion through a pointer
to the fun tion is used. The qsort fun tion provided by C is made exible by
allowing the user to hoose their own omparison fun tions.
The te hnique of writing fun tions whi h deal with a parti ular stru ture
or problem, but use some fun tion whi h is supplied by the user to ustomise
the behaviour of the fun tion to the exa t situation is sometimes alled metaprogramming.
Erlang allows fun tions to be alled by name. The apply fun tion exe utes
the fun tion named in its arguments with a supplied set of arguments. Two
forms of apply are supported by Erlang:
retval = apply(module , fun tion , [args : : : ℄)
retval = apply(fmodule , fun tion g, [args : : : ℄)

The return value, retval , is the value returned by exe uting the fun tion
module:fun tion with the arguments args : : :. The apply fun tion is parti ularly
useful for transforming lists and other data stru tures.
The lassi example of apply is the map fun tion. This fun tion applies the
supplied fun tion to ea h element of a list. An implementation of this fun tion
is shown in gure 6.2 and a sample of its output is shown in gure 6.3.
6.1

Resour es

The ode les mentioned in this hapter are:
ptf.
map.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/meta.

53

54

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

CHAPTER 6.

META-PROGRAMMING

#in lude <stdio.h>
#in lude <stdlib.h>
har strarr[5℄[10℄ =
{
"one", "two", "three", "four", "five"
};
int intarr[5℄ =
{
5, 4, 3, 2, 1
};
int str mp( onst void *, onst void *);
int int mp( onst void *a, onst void *b)
{
if (* (int *) a > * (int *) b)
return 1;
else if (* (int *) a < * (int *) b)
return -1;
else
return 0;
}
int main(void)
{
int i;
for (i=0; i < 5; i++)
printf("%s ", strarr[i℄);
printf("\n");
qsort(strarr, 5, 10, &str mp);
for (i=0; i < 5; i++)
printf("%s ", strarr[i℄);
printf("\n");
for (i=0; i < 5; i++)
printf("%d ", intarr[i℄);
printf("\n");
qsort(intarr, 5, sizeof(int), &int mp);
for (i=0; i < 5; i++)
printf("%d ", intarr[i℄);
printf("\n");
return 0;
}

Figure 6.1: Sorting with qsort in C: ptf.

6.2.

1
2
3
4
5
6
7
8
9
10

55

EXERCISES

-module(map).
-export([map/2℄).
map(L, Fn) ->
map(L, [℄, Fn).
map([℄, N, Fn) ->
N;
map([H|T℄, N, Fn) ->
map(T, [apply(Fn, [H℄) | N℄, Fn).

Figure 6.2: Sour e ode for map : map.erl
% erl
Erlang (JAM) emulator version 4.5.3
Eshell V4.5.3 (abort with ^G)
1> map:map([[1,2,3℄,[℄,[a,b℄℄,{erlang,length}).
[2,0,3℄
2>

Figure 6.3: Exer ising map.erl
6.2

Exer ises

1. Write a fun tion whi h takes a list of lists and applies the head of the
inner list as a fun tion to the arguments remaining in the inner list. The
results of this fun tion should be returned as a list.
2. Write a version of map whi h applies its fun tion to ea h element of ea h
list in a potentially in nitely deep list of lists. The list of lists stru ture
must be retained.

56

CHAPTER 6.

META-PROGRAMMING

Chapter 7

Writing EÆ ient Code
Erlang is a relatively impoverished programming language in terms of the number of me hanisms it o ers the programmer. This limits the omplexity of the
language, making it easy for programmers to learn and master. However, the
absen e of me hanisms like iteration make it harder for the programmer to ommuni ate with the ompiler the intention of the writer's ode and hen e make
it harder for the ompiler to generate eÆ ient ode.
This hapter overs methods used to make Erlang ode both time and spa e
eÆ ient.
7.1

Last Call Optimisation

A simple model of a omputer program onsists of a sta k, some memory and
a set of instru tions ( ode ) that operate on these elements (see gure 7.1).
The sta k is used to store ontext information for fun tions and pro edures.
Arguments and a return address are pushed onto the sta k before a fun tion is
alled, these arguments are preserved until the fun tion returns. Variables lo al
to a fun tion are also allo ated on the sta k. This allows a fun tion to all other
fun tions to do work for it without the other fun tions disturbing values lo al
to the alling fun tion. A sta k pointer (SP ) and a base pointer (BP ) are used
to identify where the sta k ends and where the return address is lo ated.
In pro edural languages, su h as C and Ada, iteration onstru ts su h as
loops are used to repeat operations. Erlang does not support iteration dire tly in
the language and, furthermore, prevents the values of variables being reassigned.
A naive implementation of Erlang would add a new sta k frame to the sta k
ea h time a fun tion was alled and the system would soon run out of memory.
Fortunately there exists a ase in whi h an Erlang fun tion never returns
to its alling fun tion. In this ase the alling sta k frame an be overwritten
(provided the original return address is preserved) with the new sta k frame
and as a result the sta k does not grow.
If the last a tion of a lause is to all another fun tion then the sta k frame
of the alling fun tion an be overwritten. The overwriting of the sta k frame
is alled last all optimisation. It is highly desirable to write lauses so that
the last a tion of the lause is a fun tion all as it both saves time and spa e.
Time savings are gained in that an additional sta k frame does not need to be
57

58

CHAPTER 7.

Memory

SP

WRITING EFFICIENT CODE

Free
Local
Variables

BP

Ret Addr

Stack
Frame

Parameters
Code

Previous
Functions
Stack
Frames
Stack

Figure 7.1: A Simple Model of a Program
traversed on returning from a fun tion and spa e is saved by preventing sta k
growth.
Figure 7.2 shows two implementations of the length fun tion whi h omputes
the length of a list. Both implementations are based on the observations that a
list is one item larger than a list with the rst element removed and a list with
no elements has zero length. The rst implementation, len1 , uses a straight
forward translation of the observations and as a onsequen e onsumes one
sta k frame for ea h element in the list. The se ond implementation, len2 , is
more onservative in its use of the sta k. Ea h time the nal lause is alled its
sta k frame is repla ed resulting in more ompa t exe ution.
The se ond implementation an take advantage of last all optimisation sin e
there are no operations remaining in the alling fun tion whi h must be performed after the all to the new fun tion.
7.2

Hashable Constru tions

There are wide range of Erlang ompilers deployed. This se tion will des ribe
some programming pra ti es that will allow suitably equipped Erlang ompilers
to produ e faster ode. The emphasis in this se tion is to dis uss te hniques
whi h do not unduly ompli ate ode nor slow down ode on ompilers whi h
are not tted with these optimisations. Some programming onstru tions in
Erlang are well suited to optimisation.
A ommon optimisation for pattern mat hing language ompilers is to examine the arguments for the pattern mat h and generate a hash of the arguments.
This hash is used to jump dire tly to a fun tion lause or ase lause rather
than performing a sequential mat h. Some Erlang ompilers support this opti-

7.2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

HASHABLE CONSTRUCTIONS

59

-module(len2).
-export([len1/1, len2/1℄).
len1([H|T℄) ->
1 + len1(T);
len1([℄) ->
0.
len2(L) ->
len2(0, L).
len2(N, [℄) ->
N;
len2(N, [H|T℄) ->
len2(N+1, T).

Figure 7.2: Two implementations of length : len2.erl
misation on the rst argument of a fun tion head and the rst argument of a
ase head.
Bit stuÆng in the HDLC proto ol will be used as an example of how a
fun tion an be oded to take advantage of these optimisations. HDLC is a link
level proto ol whi h uses the sequen e 01111110 to designate both the beginning
and the end of the message. This sequen e annot appear in the payload of the
message on the wire. If sender of the message wants to transmit the data
01111110 to the re eiver it is ne essary to alter the data transmitted and to
re over the original pattern at the re eiving end of the link. The algorithm used
is:

Transmitter:

If the previous ve digits have been ones send a zero then transmit the next bit in the stream
Otherwise, Transmit ea h bit as it appears
Re eiver:
If the previous ve digits have been ones and a zero arrives the
zero is dis arded.
If the previous six digits have been ones and a zero arrives then
the end of frame has been en ountered.
If the previous six digits have been ones and a one arrives then
an error has o urred.

Figure 7.3 shows an unoptimised implementation of the HDLC proto ol.
Figure 7.4 shows an improved version. The improvements onsist of greater use
of fun tion heads for de ision making and a reordering of the fun tion arguments
to allow hashing on the rst argument to be exploited. A side e e t of the rewrite
has been to improve readability, the presen e of two states { message and start
{ in the de oder has been made learer.

60

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

CHAPTER 7.

WRITING EFFICIENT CODE

-module(hdl ).
-export([en /1,de /1℄).
delimit() ->
[ 0, 1, 1, 1, 1, 1, 1, 0℄.
en (L) ->
X = en (L, 0),
lists:append(delimit(), lists:append(X, delimit())).
en (L, 5) ->
[0 | en (L, 0)℄;
en ([H|T℄, N) ->
if
H == 1 ->
[1 | en (T, N+1)℄;
H == 0 ->
[H | en (T, 0)℄
end;
en ([℄, _) ->
[℄.
de (L) ->
{Code, List} = de (L, start, [℄),
{Code, lists:reverse(List)}.
de ([0, 1, 1, 1, 1, 1, 1, 0 | T℄, start, _) ->
de (T, message, [℄);
de ([H | T℄, start, _) ->
de (T, start, [℄);
de ([℄, start, _) ->
{error, [℄};
de ([0, 1, 1, 1, 1, 1, 1, 0 | T℄, message, L) ->
{ok, L};
de ([1, 1, 1, 1, 1, 1 | T℄, message, L) ->
{error, L};
de ([1, 1, 1, 1, 1, 0 | T℄, message, L) ->
de (T, message, [1, 1, 1, 1, 1 | L℄);
de ([H|T℄, message, L) ->
de (T, message, [H | L℄);
de ([℄, message, L) ->
{error, L}.

Figure 7.3: An Implementation of the HDLC Proto ol: hdl .erl

7.2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

61

HASHABLE CONSTRUCTIONS

-module(hdl 2).
-export([en /1,de /1℄).
delimit() ->
[ 0, 1, 1, 1, 1, 1, 1, 0℄.
en (L) ->
X = en (0, L),
lists:append(delimit(), lists:append(X, delimit())).
en (5, L) ->
[0 | en (0, L)℄;
en (N, [1|T℄) ->
[1 | en (N+1, T)℄;
en (N, [0|T℄) ->
[0 | en (0, T)℄;
en (_, [℄) ->
[℄.
de (L) ->
{Code, List} = de (start, L, [℄),
{Code, lists:reverse(List)}.
de (start, [0, 1, 1, 1, 1, 1, 1, 0 |
de (message, T, [℄);
de (start, [H | T℄, _) ->
de (start, T, [℄);
de (start, [℄, _) ->
{error, [℄};
de (message, [0, 1, 1, 1, 1, 1, 1, 0
{ok, L};
de (message, [1, 1, 1, 1, 1, 1 | T℄,
{error, L};
de (message, [1, 1, 1, 1, 1, 0 | T℄,
de (message, T, [1, 1, 1, 1,
de (message, [H|T℄, L) ->
de (message, T, [H | L℄);
de (message, [℄, L) ->
{error, L}.

T℄, _) ->

| T℄, L) ->
L) ->
L) ->
1 | L℄);

Figure 7.4: An Improved Implementation of the HDLC Proto ol: hdl 2.erl

62

CHAPTER 7.

7.3

WRITING EFFICIENT CODE

Resour es

The ode les mentioned in this hapter are:
len2.erl
hdl .erl
hdl 2.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/eff.
7.4

Exer ises

1. Examine your earlier programs and determine where last all optimisation
an be applied to them. Rewrite the programs and on rm that the new
programs provide the same answers as the original programs.

Chapter 8

Robust Programs
Running programs an fail for many reasons. Some of these failures an be
ontrolled by the programmer, others are beyond the programmer's ontrol.
Robust systems must ontinue to fun tion in the fa e of unexpe ted problems.
Robust programs must be able to handle problems su h as a la k of a riti al
resour e like memory or disk spa e. Erlang provides a number of me hanisms
that allow robust programs to be written. This hapter des ribes some of those
me hanisms.
8.1

Cat h and Throw

Ex eption me hanisms are provided by many languages in luding C++, Java,
and Ada. Instead of s attering error trapping ode throughout a program, the
ex eption me hanism allows error handling ode to be entralised. Under the
ex eption paradigm, when a fun tion en ounters a problem that it annot deal
with an ex eption data stru ture is generated. The fun tion stops and the ex eption is propagated up through ea h of the subroutines whi h are awaiting
return values and aused the subroutine where the ex eption o urred to be
alled. The alling subroutines an hoose to handle the ex eption and pro essing resumes in the ex eption handler with the ex eption data stru ture provided
as an argument. Figure 8.1 shows a typi al implementation of an ex eption in
C++.
Erlang provides at h and throw me hanism whi h resembles the ex eption
me hanism. In Erlang, the argument to throw is thrown up the hain of alling
fun tions until it is aught by a at h. Note: Unlike C++ or Ada where an
ex eption an be handled or passed on to another ex eption handler, Erlang
requires that the rst at h en ountered handle the result of a throw.
Failures an result in throw like behavior. If a mat h operation fails, a fun tion is evaluated with an in orre t or unsupported argument, or an arithmeti
expression is evaluated with an invalid argument, then the Erlang run time
system generates a throw ontaining a reason for the failure.
If a failure or a throw is not aught then the default behavior of the run
time system is to terminate the pro ess that failed abnormally.
Figure 8.2 shows how at h ode an be used to prote t a divide operation
from bad data. Figure 8.3 shows the result of alling the ode with various
63

64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

CHAPTER 8.

ROBUST PROGRAMS

#in lude <iostream.h>
lass DivZeroErr
{
publi :
DivZeroErr() {}
};
int div(int a, int b)
{
if (b == 0)
throw DivZeroErr();
return(a / b);
}
int main()
{
int a, b, r;
in >> a >> b;
try
{
r = div(a, b);
out << r << endl;
}
at h (DivZeroErr error)
{
out << "Attempt to Divide by Zero" << endl;
}
}

Figure 8.1: An Example of Ex eption Handling in C++: div.C
orre t and in orre t data.
Two types of errors generated by the Erlang run time system are shown in
gure 8.3. The rst and se ond errors are the produ t of the io:read fun tion
returning something other than the pattern fok, [A, B℄g. These resulted in a
badmat h error. The nal error shown was a result of attempting to divide by
zero and a badarith error was returned.
The syntax of the at h operator is unusual in that it and its arguments
must be surrounded by parenthesis. The syntax of the operator is shown below:
( at h expr )
The expression expr is evaluated and if no failure or throw o urs in the
expression at h returns the result of the evaluation. If a failure or a throw
o urs then at h returns a data stru ture. This data stru ture is either the
argument of a throw or generated by the run time system.
Throw looks and behaves like a fun tion, ex ept it never returns. The syntax
of throw is shown below:

throw(expr )
The expression is evaluated and the result is passed to the nearest at h.
Throw an be used to simulate failures whi h would normally be generated by

8.1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

CATCH AND THROW

-module(divide).
-export([divide/0℄).
divide() ->
X = ( at h getarg()),
ase X of
{'EXIT', Reason} ->
io:format("Error ~w~n", [X℄);
{A, B} ->
Y = ( at h divide(A, B)),
ase Y of
{'EXIT', Reason} ->
io:format("Error ~w~n", [Y℄);
Y -> Y
end
end.
getarg() ->
{ok, [A, B℄} = io:fread('Enter 2 numbers > ', "~d ~d"),
{A, B}.
divide(A, B) ->
D = A div B,
io:format("~w~n", [D℄).

Figure 8.2: Prote ting Divide: divide.erl
% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> divide:divide().
Enter 2 numbers > 4 2
2
ok
2> divide:divide().
Enter 2 numbers > 1 2
0
ok
3> divide:divide().
Enter 2 numbers > a 1
Error {'EXIT',{{badmat h,error},{divide,getarg,0}}}
ok
4> divide:divide().
Enter 2 numbers > 1 a
Error {'EXIT',{{badmat h,error},{divide,getarg,0}}}
ok
5> divide:divide().
Enter 2 numbers > 2 0
Error {'EXIT',{badarith,{divide,divide,2}}}
ok
6>

Figure 8.3: Exer ising divide.erl

65

66

CHAPTER 8.

ROBUST PROGRAMS

the run time system.
Some ommon failures generated by the run time system in lude:

badarg is aused by attempting to use an in orre t argument type with a
fun tion. Eg. math:sin(a)

badarith is aused by providing an invalid argument to a mathemati al operator. Eg. 1 + a

badmat h is aused by attempting to assign to an in ompatible pattern. Eg.

fok, [A℄g = ffoog

ase lause o urs when no lause of a ase statement mat hes the argument
of ase. Eg.

ase {1,2} of
{A} -> 1;
{A,B,C} -> 3;
{A,B,C,D} -> 4
end

fun tion lause o urs when no fun tion lause mat hes the argument of a
the fun tion. Eg. bin:bin(2)
-module(bin).
-export([bin/1℄).
bin(0) -> 0;
bin(1) -> 1.

if lause o urs when no if lause is true. Eg.
if
end

a == b -> 1;
b == -> 3

no at h is aused by a throw not being aught.
nopro is aused by attempting to link (see se tion 8.5) to a non-existent
pro ess.

timeout value is aused by attempting to use a non-integer as a timeout period in a re eive. Eg.

re eive
X -> X
after 3.4 ->
timeout
end

unbound is aused by attempting to a ess an unbound variable.

8.2.

TERMINATION

67

undef is aused by attempting to a ess a fun tion whi h has not been de ned.
Eg. string:len("ab ","a")

Sometimes it is not onvenient or possible to handle a failure at the rst at h
en ountered. In this ase the at h an re-throw the failure data stru ture to
allow the failure to be handled at a higher level.
Figure 8.4 shows a program that adds hexade imal numbers and outputs
the result in de imal. The program uses at h and throw failure dete tion and
generation. The hexde fun tion transforms one type of error (fun tion lause )
aused by the presen e of a non-hexade imal digit into a bad har error. In
addition the fun tion re-throws thrown 2 element tuples ontaining the fail
atom.
The output of the program is shown in gure 8.5. The se ond exe ution
sequen e was aused by entering a spa e at the prompt, resulting in an empty
list being passed to the hex vt fun tion.
The at h and throw onstru t an be used to generate a non-lo al return
from a fun tion. Results an be passed dire tly up the all hain, avoiding
intermediate fun tions by throwing the result to a at h. This pra ti e an lead
to onfusing ode and should be used with are.
8.2

Termination

A pro ess an be terminated either by returning from the fun tion that the
pro ess was started with or by alling the exit fun tion.
The result of an exit o urring within the s ope of a at h an be trapped
using at h.
Exit looks and behaves like a fun tion, ex ept it never returns. Exit generates
a signal of the form f`EXIT`, Reasong. Signals are similar to the data thrown
by a throw to the extent that they an be aught by a at h. Signals an be
generated by the pro ess re eiving them or by another pro ess whi h knows the
pid of the pro ess to whi h the signal is to be sent. The syntax of exit is shown
below:

exit(expr )
The expression expr is evaluated and the result be omes the reason either
aught by a at h or displayed by the interpreter. The atom normal is spe ial in that when a pro ess exits normally no error report is displayed by the
interpreter.
Another form of the exit fun tion operates on pro esses other than the
aller.

exit(pid , expr )
This fun tion returns to its alling pro ess. The pro ess named by pid is
signaled with the reason resulting from evaluating expr . The named pro ess
then behaves as if it had exe uted exit(expr ).
Note that the se ond form of exit annot be aught by a at h as it o urs
outside the s ope of the at h.

68

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

CHAPTER 8.

ROBUST PROGRAMS

-module(hex).
-export([hexde /1, hexadd/0℄).
hexadd() ->
X = ( at h adder()),
ase X of
{'EXIT', Reason} ->
io:format("Error ~w~n", [X℄);
{fail, bad har} ->
io:format("Error hex digits must are 0-9 a-f~n");
{fail, nullarg} ->
io:format("Error value required~n");
Y -> Y
end.
adder() ->
{ok, [A℄} = io:fread('Enter first number > ', "~a"),
{ok, [B℄} = io:fread('Enter se ond number > ', "~a"),
hexde (A) + hexde (B).
hexde (Atom) ->
L = atom_to_list(Atom),
ase ( at h hex vt(L)) of
{'EXIT', {fun tion_ lause, _}} ->
throw({fail, bad har});
{fail, X} ->
throw({fail, X});
R -> R
end.
hex vt([℄) ->
throw({fail, nullarg});
hex vt(L) ->
hex vt(L, 0).
hex vt([℄, N) ->
N;
hex vt([H|T℄, N) ->
V = de val(H),
hex vt(T, N * 16 + V).
de val($0)
de val($3)
de val($6)
de val($9)
de val($ )
de val($f)

->
->
->
->
->
->

0;
3;
6;
9;
12;
15.

de val($1)
de val($4)
de val($7)
de val($a)
de val($d)

->
->
->
->
->

1;
4;
7;
10;
13;

de val($2)
de val($5)
de val($8)
de val($b)
de val($e)

->
->
->
->
->

2;
5;
8;
11;
14;

Figure 8.4: Hex Conversion and Addition: hex.erl

8.3.

ERROR HANDLERS

69

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> hex:hexadd().
Enter first number > 1
Enter se ond number > 2
3
2> hex:hexadd().
Enter first number > 1
Enter se ond number >
Error value required
ok
3> hex:hexadd().
Enter first number > 1
Enter se ond number > g
Error hex digits must are 0-9 a-f
ok
4> hex:hexadd().
Enter first number > 1
Enter se ond number > a
11
5>

Figure 8.5: Exer ising hex.erl
8.3

Error Handlers

Erlang de nes a number of default behaviors whi h o ur in response to parti ular types of errors. These behaviors are de ned by the error handler module.
This module an be repla ed by alling pro ess ag(error handler, module ),
where module is the name of the module ontaining fun tions whi h implement
the interfa es des ribed below.
When an unde ned fun tion o urs error handler:unde ned fun tion is invoked:
unde ned fun tion(module , fun , Args )
where module is the name of the module, fun is the name of the fun tion
and Args is the list of arguments.
When an unde ned global name o urs error handler:unde ned global name
is invoked:
unde ned global name(name , message )
where name is the name, and message is the message sent to the unde ned
name.
These fun tions operate in a ompli ated and sensitive environment. Changing the default behavior is risky and may lead to system deadlo k.

70

CHAPTER 8.

8.4

ROBUST PROGRAMS

Defensive Programming

Data provided to an Erlang program an ause a run time failure. Causes for
these failures in lude division by zero or being unable to mat h a pie e of data.
Programs need to guard against the problems introdu ed by bad data. Two
strategies are available: 

A test before use strategy ensures that data is orre tly formatted and
meets pre onditions before using it. 

A try and re over if ne essary strategy pro eeds as if the data is orre t
and only worries about error handling if an error o urs.

The former strategy is useful if performing part of an operation without ompleting is undesirable. The latter strategy is in general more desirable. Error
trapping ode adds to the omplexity and size of the working ode, the se ond
strategy redu es the volume of error trapping ode and allows it to be separated
from the ode that handles the general ase. If errors tend to be rare events,
traversing ode to prevent errors adds a ost to ea h run for an event that o urs
infrequently. The se ond strategy eliminates the test ode for the general ase.
The programs in gures 8.6 and 8.7 divide 2 integers to produ e a dividend.
The ode in gure 8.6 guards data by testing to see if it is valid before use. A
try and re over if ne essary strategy is used by the ode in gure 8.7.
8.5

Linked Pro esses

Erlang pro esses may be linked to other Erlang pro esses. Links are bidire tional. The linking me hanism is used to notify linked pro esses of the failure
of a pro ess. This noti ation takes the form of a signal:
'EXIT' , Exiting PID , Reason

If the Reason is not normal and a linked pro ess does not handle the exit
signal then the linked pro ess will terminate and send exit signals to all its
linked pro esses.
Links an be reated when a pro ess is spawned or they an be added or
removed after a pro ess has been spawned. The spawn link fun tion reates a
pro ess and links the urrent pro ess to it.

spawn link(Module , Fun tion , Arglist )
The spawn link fun tion takes the same arguments as spawn, after the

arguments are evaluated a new pro ess is reated and started by alling Module:Fun tion with the arguments ontained in Arglist . The fun tion link reates
a link between pro esses:

link(Pid )
If a link already exists the link fun tion has no e e t. If the pro ess does
not exist an exit signal of the form f'EXIT', PID, nopro g is generated in the
pro ess alling link. A link between two pro esses is removed using the unlink
fun tion.

unlink(Pid )

8.5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

LINKED PROCESSES

-module(divide2a).
-export([divide/0℄).
divide() ->
io:format("Enter numbers "),
{R1, A} = readint(),
{R2, B} = readint(),
if
R1 == ok, R2 == ok ->
if
B =/= 0 ->
D = A div B,
io:format("~w~n", [D℄),
D;
true ->
io:format("Attempt to divide by zero~n"),
divide()
end;
true ->
io:format("Please enter 2 numbers~n"),
divide()
end.
readint() ->
io:format("> "),
{ok, [L℄} = io:fread('', "~s"),
Len = string:span(L, "0123456789"),
if
Len == 0 ->
{nodata, 0};
true ->
V = list_to_integer(string:substr(L,1,Len)),
{ok, V}
end.

Figure 8.6: Handing Bad Data: divide2a.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

-module(divide2b).
-export([divide/0℄).
divide() ->
ase ( at h getdiv()) of
{'EXIT', Reason} ->
io:format("Error ~w~n", [Reason℄),
divide();
X -> X
end.
getdiv() ->
{ok, [A, B℄} = io:fread('Enter 2 numbers > ', "~d ~d"),
D = A div B,
io:format("~w~n", [D℄).

Figure 8.7: Handling Bad Data: divide2b.erl

71

72

CHAPTER 8.

ROBUST PROGRAMS

This fun tion has no e e t if there is no link between the urrent pro ess
and the named pro ess. As links are bidire tional, this all removes both the
link from both the aller and the named pro ess.
8.6

Trapping Exits

Two forms of the exit are supported in Erlang. An exit exe uted by a pro ess
an be aught by a pro ess using at h. Exits from outside a pro ess are aused
either by a link or using the two argument form of exit. Exits from outside
a pro ess annot be aught by a at h. Erlang provides a pro ess ag whi h
allows these external signals to be onverted to messages. Exe uting
pro ess ag(trap exit, true)
auses all in oming signals to be onverted to messages so that they an be
handled.
8.7

Robust Servers

Self healing is a highly desirable property in a long running system. The se tion
des ribes how a server an be implemented and monitored so that the servi e
an be restarted and hen e provide near ontinuous availability of a servi e.
Figure 8.8 shows the ode for restart . This pro ess monitors its hildren and
restarts them when they fail, ensuring servi e availability. It does not address
the issues of preserving state or re overy.
The restart pro ess is shown in a tion with the mto on program. The sour e
for mto on is shown in gure 8.9. The output of the run is shown in gure 8.10.
The ode in gures 8.8 and 8.9 employ the following me hanisms and te hniques to provide a robust servi e to their lients: 

Registered Names: Both programs employ registered names to provide
easy a ess to the servi e. The mto on relies on the use of registered
names to provide ontinuity of referen e to the servi e after it is restarted. 

Defensive Programming: is employed by the restart program. Bad data
is guarded against when a pro ess is reated using at h on lines 21 and
57. Failures are ignored by returning an un hanged list. Su ess results
in the list of pro esses being hanged. 

Exit Trapping: is used by the restart program to determine when its
lients have failed and to initiate an attempt to restart them.

8.7.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

ROBUST SERVERS

-module(restart).
-export([start/0, init/0, add/3, remove/3℄).
start() ->
spawn(restart, init, [℄).
init() ->
pro ess_flag(trap_exit, true),
register(restart, self()),
manage([℄).
add(M, F, A) ->
restart ! {add, M, F, A}.
remove(M, F, A) ->
restart ! {remove, M, F, A}.
manage(ListPro ) ->
NewList = re eive
{add, Moda, Funa, Arga} ->
ase ( at h newpro (Moda, Funa, Arga, ListPro )) of
X when list(X) ->
X;
_ ->
ListPro
end;
{remove, Modr, Funr, Argr} ->
rempro (Modr, Funr, Argr, ListPro );
{'EXIT', Pid, Reason} ->
restart(Pid, ListPro );
Unknown ->
ListPro
end,
manage(NewList).
newpro (M, F, A, L) ->
Pid = spawn_link(M, F, A),
[{M, F, A, Pid} | L℄.
rempro (M, F, A, L) ->
rempro (M, F, A, L, [℄).
rempro (M, F, A, [℄, L) ->
L;
rempro (M, F, A, [{HM, HF, HA, HP}|T℄, L)
when M==HM, F==HF, A==HA ->
rempro (M, F, A, T, L);
rempro (M, F, A, [H|T℄, L) ->
rempro (M, F, A, T, [H|L℄).
restart(P, L) ->
restart(P, L, [℄).

73

74
53
54
55
56
57
58
59
60
61
62
63
64
65

CHAPTER 8.

ROBUST PROGRAMS

restart(P, [℄, L) ->
L;
restart(P, [{HM, HF, HA, HP}|T℄, L) when P==HP ->
NL = ase ( at h newpro (HM, HF, HA, T)) of
X when list(X) ->
X;
_ ->
T
end,
lists:append(NL, L);
restart(P, [H|T℄, L) ->
restart(P, T, [H|L℄).

Figure 8.8: A Program to Restart Pro esses: restart.erl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

-module(mto on).
-export([start/1℄).
start(N) ->
register(N, self()),
io:format("Starting ~w~n", [N℄),
loop(N).
loop(N) ->
re eive
{exit, Reason} ->
io:format("Exiting ~w be ause ~w~n", [N, Reason℄),
exit(Reason);
X ->
io:format("~w re eived ~w", [N, X℄)
end,
loop(N).

Figure 8.9: A Program That Outputs its Messages: mto on.erl
8.8

Generi Servers

The gen server module provides the basi servi es required to implement a
server. The module uses allba k fun tions to provide the spe i behavior
required for the servi e. A allba k is a hieved by passing the module and
fun tion names to the generi server. The use of generi servers is en ouraged
as it allows the programmer to fo us on writing the sequential parts of the
servi e, and eliminates the need to test the shared server omponent ea h time
a server is written.

8.8.

GENERIC SERVERS

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> restart:start().
<0.28.0>
2> restart:add(mto on,start,[one℄).
{add,mto on,start,[one℄}
Starting one
3> restart:add(mto on,start,[two℄).
{add,mto on,start,[two℄}
Starting two
4> one ! hi.
one re eived hihi
5> two ! hi.
two re eived hihi
6> one ! {exit, normal}.
Exiting one be ause normal
{exit,normal}
Starting one
7> one ! hi.
one re eived hihi
8> restart:remove(mto on,start,[one℄).
{remove,mto on,start,[one℄}
9> one ! hi.
one re eived hihi
10> one ! {exit, done}.
Exiting one be ause done
{exit,done}
11> one ! hi.
=ERROR REPORT==== 10-Jun-1998::10:29:17 ===
<0.21.0> error in BIF send/2(one,hi)
<0.21.0> error: badarg in erl_eval:eval_op/3
** exited: {badarg,{erl_eval,eval_op,3}} **
12> two ! hi.
two re eived hihi
13> restart:add(mto on,stop,[one℄).
{add,mto on,stop,[one℄}
14> restart:add(mto on,start,[three℄).
{add,mto on,start,[three℄}
Starting three
15> three ! hi.
three re eived hihi
16> restart:remove(mto on,start,[two℄).
{remove,mto on,start,[two℄}
17> restart:remove(mto on,start,[three℄).
{remove,mto on,start,[three℄}
18> three ! {exit, done}.
Exiting three be ause done
{exit,done}
19>

Figure 8.10: Exer ising restart.erl with mto on.erl

75

76

CHAPTER 8.

8.9

ROBUST PROGRAMS

Resour es

The ode les mentioned in this hapter are:
div.C
divide.erl
hex.erl
divide2a.erl
divide2b.erl
restart.erl
mto on.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/robust.

Further information on the gen server module an be found in the `The Standard Erlang Libraries: Referen e Manual' in `Open Tele om Platform (OTP)'
do umentation set by Eri sson Software Te hnology AB, Erlang Systems. This
do umentation is provided in HTML and Posts ript form with the Erlang distribution.
8.10

Exer ises

1. Identify some of the faults whi h restart ( gure 8.8) does not address.
Suggest alterations to the ode that would allow restart to address these
faults.
2. The Roman satirist Juvenal re e ted `Quis ustodiet ipsos ustodes?'
whi h may be translated as `Who is to guard the guards themselves?'
Des ribe the problems likely to be en ountered in building a robust server
and identify a strategy for onstru ting a robust server.

Chapter 9

Code Repla ement
Some ommer ial systems run for many years at a time with no opportunity
for downtime. Telephone ex hanges and power grids are examples of systems
where a design obje tive is to have one hundred per ent availability. Based
on experien es drawn from other ommer ial omputing endeavors, it would be
unreasonable to expe t that ode used in these systems would be orre t in all
aspe ts and not require alteration during the life of the system. The normal
mode of ode repla ement, bringing down the system and restarting it with
new ode is una eptable for this type of system. Erlang was designed with
telephone ex hanges as an appli ation, and provides a me hanism for repla ing
parts of the program ode while the system remains running.
This hapter dis usses the me hanisms that Erlang provides for ode loading
and repla ement.

9.1

Loading and Linking

Erlang groups fun tions into olle tions alled modules. Loading is the pro ess
of reading a module into the systems memory for use. Linking is the pro ess of
resolving names to addresses. Linking an be arried out on e when a program
is ompiled (stati linking) or it an be deferred until a program is running
(dynami linking).
Modules are loaded into memory when a fun tion in that module is rst
named.
Erlang dynami ally links a module when a fully quali ed fun tion name is
used for a fun tion ontained in that module. A fully quali ed name onsists
of the module name and the fun tion name separated by a olon. Ea h time a
fully quali ed fun tion name is en ountered the ode transfers exe ution to the
latest instan e of the module loaded.
Fun tions named in a module, that are referred to only by the fun tion name
(not fully quali ed) are stati ally linked at ompile time. Stati linkages annot
be altered at run time.
77

78

CHAPTER 9.

9.2

CODE REPLACEMENT

Code Repla ement

Modules are the base unit of ode repla ement. More than 1 image of a module
may be present in memory at one time ( urrent systems support a maximum of
2 images). When a fully quali ed all is made the fun tion named is exe uted
from the latest version of the module urrently in memory. Partially quali ed
referen es, whether internal (stati ) or from an import lause refer to the version
of the module present when the fully quali ed all was made.
An arti ial example of ode repla ement is shown in gures 9.1 and 9.2.
The ode in gure 9.1 is modi ed half way through the output shown in gure
9.2 hanging the version number from 1 to 2 .
1
2
3
4
5
6
7
8
9
10
11
12

-module( oderep).
-export([msglp/0℄).
vers() ->
1.
msglp() ->
Msg = re eive
X -> X
end,
io:format("~w ~w~n", [Msg, vers()℄),
oderep:msglp().

Figure 9.1: Sour e ode for oderep (initial version): oderep.erl
In the example a new version of the ode is reated at the 6th step in gure
9.2 by re ompiling the altered module. The new ode is rst used at the end
of the 7th step when the fully quali ed fun tion all oderep:msglp is exe uted.
When that statement is exe uted the new module is loaded into memory and
ontrol is transfered to it. All referen es to the fun tion vers are stati ally linked
at ompile time. The result of the ode hange is seen at the 8th step when the
version number is shown as 2 .
9.3

Limitations

In se tion 9.2 it was noted that only 2 images of a module are supported on urrently. If a pro ess requires an old image and it is moved out of memory, the
pro ess an no longer run. Figure 9.3 illustrates a pro ess that uses old ode
and gure 9.4 shows how it fails.
When the pro ess attempts to a ess the old fun tion stale in the original
module, it fails as the ode has been displa ed by 2 newer instan es of the
module.
9.4

Code Management

Erlang provides a set of fun tions to manage module images and the pro esses
running old images. These fun tions an be used to avoid the problem demon-

9.4.

CODE MANAGEMENT

79

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> ( oderep).
{ok, oderep}
2> Pid=spawn( oderep,msglp,[℄).
<0.32.0>
3> Pid ! 1.
1 1
1
4> Pid ! 2.
2 1
2
5> Pid ! 3.
3 1
3
6> ( oderep).
{ok, oderep}
7> Pid ! 1.
1 1
1
8> Pid ! 2.
2 2
2
9> Pid ! 3.
3 2
3
10>

Figure 9.2: Demonstrating Code Repla ement
strated in se tion 9.3. The interfa e to the management fun tions is found in
the ode module. The fun tions found in this module in lude:
The load le fun tion attempts to load the named Erlang module. If the
module loaded repla es an existing module the existing module is made old and
any other opies of the module are removed from memory.
load le(Module)
The delete fun tion makes the ode for Module old. New invo ations of the
module will not be able to a ess the deleted module. It returns true on su ess,
and false on failure.
delete(Module)
The purge fun tion removes the ode of the named module marked as old
from the system. Pro esses running the old module ode will be killed. If a
pro ess has been killed the fun tion returns true , otherwise false .
purge(Module)

80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

CHAPTER 9.

CODE REPLACEMENT

-module(stale).
-export([start/0, stale/0, vers/0℄).
vers() ->
1.
start() ->
spawn(stale, stale, [℄).
stale() ->
re eive
startver ->
io:format("Start Version ~w~n", [vers()℄);
urver ->
io:format("Current Version ~w~n", [stale:vers()℄)
end,
stale().

Figure 9.3: Sour e for stale : stale.erl
The soft purge fun tion is similar to purge ex ept it will not purge a
module if it is urrently been used by a module. If a pro ess is using old ode
the fun tion returns false , otherwise true .
soft purge(Module)
The is loaded fun tion returns a tuple ontaining the atom le and either
the lename from whi h the module was loaded or the atoms preloaded or interpreted for loaded modules. If the module is not loaded then it returns false .
is loaded(Module)
The all loaded fun tion returns a list of tuples ontaining the name of the
module, and either the lename from whi h the module was loaded or the atoms
preloaded or interpreted for all loaded modules.
all loaded()
Using these fun tions and another me hanism of invoking the ompiler it is
possible to write a program that hanges its ode when required. The program
in gure 9.5 uses a new version of itself only after a new message is sent to it.
Figures 9.6 shows that ode an be hanged and ompiled but does not be ome
a tive until a message is sent. The ompile: le fun tion is similar to but it
does not automati ally load the ompiled module.

9.5.

81

RESOURCES

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> (stale).
{ok,stale}
2> P=stale:start().
<0.32.0>
3> P ! startver.
Start Version 1
startver
4> P ! urver.
Current Version 1
urver
5> (stale).
{ok,stale}
6> P ! startver.
Start Version 1
startver
7> P ! urver.
Current Version 2
urver
8> (stale).
{ok,stale}
9> P ! startver.
startver
10>

Figure 9.4: Pro ess Failure Caused by Code Repla ement
9.5

Resour es

The ode les mentioned in this hapter are:
oderep.erl
stale.erl
nofstale.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/ oderep.
9.6

Exer ises

1. Write some programs that use the fun tions des ribed in this hapter to
explore ode repla ement.

82

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

CHAPTER 9.

CODE REPLACEMENT

-module(nofstale).
-export([start/0, nofailstale/0, vers/0℄).
vers() ->
3.
start() ->
spawn(nofstale, nofailstale, [℄).
nofailstale() ->
Msg = re eive
X -> X
end,
nofailstale(Msg).
nofailstale(new) ->
ode:purge(nofstale),
ode:load_file(nofstale),
nofstale:nofailstale();
nofailstale(ver) ->
io:format("Start Version ~w~n", [vers()℄),
nofailstale().

Figure 9.5: Sour e for nofailstale : nofstale.erl

9.6.

83

EXERCISES

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> ompile:file(nofstale).
Erlang BEAM Compiler 4.6.4/22
Obje t file: nofstale.beam
{ok,nofstale}
2> P=nofstale:start().
<0.32.0>
3> P!ver.
Start Version 1
ver
4> P!ver.
Start Version 1
ver
5> ompile:file(nofstale).
Erlang BEAM Compiler 4.6.4/22
Obje t file: nofstale.beam
{ok,nofstale}
6> P!ver.
Start Version 1
ver
7> P!new.
new
8> P!ver.
Start Version 2
ver
9> P!ver.
Start Version 2
ver
10> ompile:file(nofstale).
Erlang BEAM Compiler 4.6.4/22
Obje t file: nofstale.beam
{ok,nofstale}
11> P!new.
new
12> P!ver.
Start Version 3
ver
13> P!ver.
Start Version 3
ver
14>

Figure 9.6: nofailstale in A tion

84

CHAPTER 9.

CODE REPLACEMENT

Chapter 10

Programming Style
This hapter provides an introdu tion to good programming style and formatting in Erlang. Readers are referred to the referen e se tion (se tion 10.6) for a
more omprehensive guide.
Many of the suggestions made in this hapter will be for parti ular onventions. Conventions are agreed means for handling spe i ed ir umstan es.
They need not be enfor ed and may be arbitrary in nature. The general use of
onventions in programming is to improve the readability and understandability
of ode. Conventions an be used to provide additional information about the
program to programming tools that is not present in the ompiled ode. This
information often relates to the intentions of the authors or the anti ipated use
of the ode.
10.1

Comments and Do umentation

Erlang provides two me hanisms for internal do umentation: omments and attributes . Figure 10.1 illustrates the do umentation onventions and implements
a semaphore.

10.1.1 Comments
Comments are introdu ed using a `%' in Erlang. A ommenting onvention
des ribes how and where omments should be used in sour e ode. In general, a
ompiler does not enfor e a onvention, however, tools an be written that he k
a onvention is at least being partly met. Furthermore, a omment onvention
an be exploited to assist in the automati generation of do umentation.
The following is the re ommended onvention for omments in Erlang:   

Module des riptions should begin with 3 per ent signs (`%%%')
Fun tion des riptions should begin with 2 per ent signs (`%%')
Comments within a fun tion should begin with 1 per ent sign (`%'). The
preferred pra ti e is to pla e the omment at the end of the line that is
being ommented on. If a omment does not t it should be pla ed on the
line above.
85

86

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

CHAPTER 10.

PROGRAMMING STYLE

-module(do ).
-author('Mauri e Castro').
- opyright('Copyright ( ) 1998').
-vsn('$Id: do .erl,v 1.4 1998/06/22 02:33:07 mauri e Exp $').
-modified('Mon Jun 22 08:38:16 EST 1998').
-modified_by('mauri eser ').
-modified('Mon Jun 22 12:17:35 EST 1998').
-modified_by('mauri eser ').
-export([start/0, start/1, p/1, v/1, msglp/2℄).
%%%
%%%
%%%
%%%
%%%
%%%
%%%
%%
%%
%%
%%

-------------------------------------------------------------This module illustrates do umentation onventions des ribed in
`Erlang in Real Time' by Mauri e Castro
It implements a Counting Semaphore as defined by Hwang K,
`Advan ed Computer Ar hite ure' M Graw Hill, 1993, p638.
Warning this ode assumes no messages are lost.
--------------------------------------------------------------

--------------------------------------------------------------This is the spe ial ase of a binary semaphore, use general
start routine to perform start.
---------------------------------------------------------------

start() ->
start(1).
%%
%%
%%
%%

--------------------------------------------------------------The start/1 fun tion starts a server and returns its pid.
This is the general ase
---------------------------------------------------------------

start(N) ->
% spawn the message loop with initial data of N
spawn(do , msglp, [N, [℄℄).
%% --------------------------------------------------------------%% P(s): if s > 0, then s = s - 1; else put in wait queue
%% --------------------------------------------------------------p(S) ->

S ! {semaphore, p, self()},
% ont requires pro ess name
% wait for a ontinue message to indi ate exiting queue
re eive
{semaphore, ont} ->
true
end.

%% --------------------------------------------------------------%% V(s): if wait queue not empty, wake up one; else s = s + 1
%% ---------------------------------------------------------------

10.1.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

COMMENTS AND DOCUMENTATION

v(S) ->

S ! {semaphore, v}.

% Server handles v

%% --------------------------------------------------------------%% The msglp fun tion handles
ases:
%% --------------------------------------------------------------msglp(S, L) ->
{NewS, NewL} = re eive
{semaphore, p, Pid} ->
if
% P(s): if s > 0, then s = s - 1;
S > 0 ->
Pid ! {semaphore, ont},
{S - 1, L};
true ->
% else put in wait queue
{S, [Pid, L℄}
end;
% V(s): if wait queue not empty,
{semaphore, v} when length(L) =/= 0 ->
[H|T℄ = L,
% wake up one;
H ! {semaphore, ont},
{S, T};
% if the list is empty on a v
{semaphore, v} ->
% else s = s + 1
{S+1, L}
end,
msglp(NewS, NewL).

Figure 10.1: Do umentation Example - Semaphore Sour e Code: do

87

88

CHAPTER 10.

PROGRAMMING STYLE

10.1.2 Attributes
A module attribute appears at the beginning of an Erlang module, before any
Erlang ode. An attribute onsists of a `-' a name and a bra keted Erlang term.

-name (term ).
A number of module attributes have spe ial meanings su h as -module(),
-export(), and -import(). Other attributes an be used for do umentation

purposes su h as identifying the reator and those who have in uen ed ode.
10.2

Modules

This se tion provides a series of re ommendations that apply to Erlang modules. 

Minimise the number of fun tions exported from a module. Re-

du es the possibility for oupling between modules to a small number of
fun tions. This minimises the number of interfa e fun tions that need to
be maintained. 

Use fun tions to en apsulate ommon ode.

Avoid ut and paste
programming, instead write a fun tion to represent the repeated aspe t of
the ode. 

Do not presume that the data stru tures provided by a module
are un hanging. A module should provide a suÆ ient interfa e to arry

out all required operations on the data stru tures it generates. If a user
knows the stru tures generated by a module they should avoid a ess the
elements of those stru tures dire tly. 

Use interfa e fun tions.

Use fun tions as an interfa e where possible.
Avoid sending messages dire tly.

10.3

Fun tions

This se tion provides a series of re ommendations that apply to Erlang fun tions. 

Avoid side e e ts. 
Do not assume what the user of a fun tion wants to do with its
results. The a t of printing an error message when an error o urs in a
fun tion assumes that the user wants an error displayed. If the error were
returned silently then the user of the fun tion ould hoose to display the
error or not.

10.4

Messages

This se tion provides a series of re ommendations that apply to Erlang messages. 

Tag messages. This redu es the sensitivity of messages to order.

10.5.

89

GENERAL 

Dispose of unknown messages.

Every server should in orporate a
mat h all pattern in at least one of its re eives to ensure that unhandleable
messages are removed from the message queue.

10.5

General

This se tion provides a series of general re ommendations. 

Avoid defensive programming.

The majority of a systems programs
should trust that their inputs are orre t. Ex eptions an be aught where
ne essary. Only a small fra tion of the ode in a system should he k its
inputs. 

Separate handling of error ases from normal ode. 
Write de laritive ode. Use guards in fun tion heads where possible

to de lare the appli ability of the ode rather than hiding the hoi es in
if and ase operations.

10.6

Resour es

The ode les mentioned in this hapter are:
do .erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/style.

Further information on programming style an be found in Eriksson, K.,
Williams, M., Armstrong, J., `Program Development Using Erlang - Programming Rules and Conventions', 1995, http://www.erlang.se/erlang/sure/
main/news/programming_rules.ps.gz or http://www.erlang.se/erlang/sure/
main/news/programming_rules.shtml.
10.7

Exer ises

1. Study the style guidelines and identify a rationale for ea h guideline.
2. Rewrite le nt ( gure 1.5) using the style re ommendations made in this
hapter.
3. Examine the examples in this book and re ommend style improvements.

90

CHAPTER 10.

PROGRAMMING STYLE

Chapter 11

Graphi s

Although Erlang supports at least 2 graphi s subsystems (gs and pxw) this
hapter will limit itself to des ribing the portable graphi s subsystem known as
gs . This subsystem was used in the previous examples of graphi al ode ( gures
1.3 and 2.9).
11.1

Model

The gs subsystem is built on an event model. Messages are sent between the
ontrolling pro ess and a gs server to ause or report events. Figure 11.1 shows
the relationship between the omponents of the system, the noti ation of an
event and an operation being performed.
Output Devices

Object
gs
Graphics
Server

Controlling
Process

Input Devices
Graphics
Hardware/Software
Event

Operation

Figure 11.1: The Components of the GS Graphi al Model
Obje ts are reated in a hierar hy. Ea h obje t has a parent and may have
91

92
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

CHAPTER 11.

GRAPHICS

-module(thrbut).
-export([init/0℄).
init() ->
Server = gs:start(),
Win = gs: reate(window, Server, [{width, 300}, {height, 80}℄),
Display = gs: reate(label, Win, [{label, {text, "0"}},
{x, 0}, {y, 0}, {width, 200}, {height, 50}℄),
Plus = gs: reate(button, Win, [{label, {text, "+"}},
{x, 0}, {y, 50}℄),
Minus = gs: reate(button, Win, [{label, {text, "-"}},
{x, 100}, {y, 50}℄),
Quit = gs: reate(button, Win, [{label, {image, "q.xbm"}},
{x, 200}, {y, 50}℄),
gs: onfig(Win, {map, true}),
event_loop(0, Display, Plus, Minus, Quit).
event_loop(N, D, P, M, Q) ->
re eive
{gs, P, li k, Data, Args} ->
RP = N+1,
gs: onfig(D, {label, {text, RP}}),
event_loop(RP, D, P, M, Q);
{gs, M, li k, Data, Args} ->
RM = N-1,
gs: onfig(D, {label, {text, RM}}),
event_loop(RM, D, P, M, Q);
{gs, Q, li k, Data, Args} ->
gs:stop(),
N
end.

Figure 11.2: Sour e Code for thrbut.erl
one or more hildren. When an obje t is reated an obje t identi er is returned
to the reator. Obje ts an be reated with a spe i ed name, allowing the
program to ontrol the hoi e of identi er.
Figures 11.2 and 11.3 show a simple example of a server with 3 buttons and
a text display. This example illustrates: 

Starting and stopping the graphi s server (lines 5 and 29) using gs:start()
and gs:stop()    

Creating a window (line 6) using gs: reate 

Creating buttons inside a window (lines 9 to 14)
Creating a label inside a window (lines 7 and 8)
Changing the options onne ted with a graphi al obje t (lines 15, 22 and
26) using gs: on g
Handling events generated in an even loop (lines 18 to 31)

11.2.

93

INTERFACE

Figure 11.3: Display from thrbut.erl
The example has a simple two level hierar hy whi h is shown in gure 11.4
(Note: the a tual names of the entities are not shown in the diagram, only the
variables in whi h the names of the graphi al obje ts were initially stored). The
hierar hy is onstru ted by naming the parents when the gs: reate fun tion
is alled. The hierar hy is used to des ribe the layout relationships between
obje ts, for instan e it allows obje ts to be grouped so that they an moved as
part of a single entity.
Window
(Win)

Label
(Display)

Button
(Minus)

Button
(Plus)

Button
(Quit)

Figure 11.4: The GS Hierar hy Found in thrbut.erl

11.2

Interfa e

11.2.1 Fun tions
The interfa e to gs is built on 6 basi fun tions: gs:start, gs:stop, gs: reate,
gs: on g, gs:destroy, and gs:read.
The gs:start fun tion starts the gs server. The fun tion takes no arguments.

An identi er is returned whi h is used as the parent for top level obje ts (windows). If the fun tion is alled more than on e it returns the same identi er.

gs:start()
The gs:stop fun tion stops the gs server and loses any windows opened by

the server. The fun tion takes no arguments.

gs:stop()

94

CHAPTER 11.

GRAPHICS

The gs: reate fun tion is used to make graphi al obje ts. The fun tion has
several forms. The types of the arguments used in the forms are: Objtype {
atom identifying obje t type; Parent { identi er returned by parent; Options
{ list of options to be set for obje t; Option { option to be set for obje t; and
Name { identi er to be used to refer to obje t. An identi er for the new obje t
is returned.

gs: reate(Objtype , Parent )
gs: reate(Objtype , Parent , Options )
gs: reate(Objtype , Parent , Option )
gs: reate(Objtype , Name , Parent , Options )
gs: reate(Objtype , Name , Parent , Option )
The gs: on g fun tion sets an option for an obje t. The fun tion has two
forms. It takes an obje t identi er or a name and either a single option value
tuple or a list of option value tuples as arguments. It returns ok on su ess or
ferror, Reasong on failure.

gs: on g(Identi er , fOption, Valueg)
gs: on g(Identi er , [fOption, Valueg : : : ℄)
The gs:destroy fun tion destroys a graphi al obje t and its hildren. The
fun tion takes an obje t identi er or a name as an argument.

gs:destroy(Identi er )
The gs:read fun tion reads a value from a graphi al obje t. The fun tion
takes an obje t identi er or a name and a key as arguments. It returns the
value read on su ess or ferror, Reasong on failure.

gs:read(Identi er , Key )

11.2.2 Obje ts
The gs subsystem provides a large number of built in graphi s obje ts whi h an
be used to onstru t displays. A sele tion of the available obje ts is dis ussed
below.
A window is a s reen obje t whi h ontains other s reen obje ts. Only windows are allowed to be top level obje ts. All other obje ts must be des endents
of a top level obje t. A window may have a window or the server as its parent.
The atom window is used to denote this obje t type.
A family of button obje ts is supported. A button is an obje t whi h may
be sele ted with a mouse. It may be sele ted or unsele ted. A button may have
a window or a frame as a parent. The atom button is used to denote a simple
button, radiobutton is used to denote a button type where only one member
of a group of buttons may be pressed at one time, and he kbutton denotes a
button type where many buttons may be sele ted in a group at one time.

11.2.

INTERFACE

95

A label is used to display either a text message or a bitmap1 . A label may
have a window or a frame as a parent. The atom label is used to denote this
obje t type.
A frame is a ontainer used to group obje ts. A frame may have a window
or a frame as a parent. The atom frame is used to denote this obje t type.
An entry allows a single line of text to be entered. An entry may have a
window or a frame as a parent. The atom entry is used to denote this obje t
type.
A listbox displays a list of strings and allows zero or more to be sele ted.
A listbox may have a window or a frame as a parent. The atom listbox is used
to denote this obje t type.
A anvas is a drawing area. The following obje ts may be present in a
anvas: ar , image 2 , line , oval , polygon , re tangle , and text . A anvas may
have a window or a frame as a parent. The atom anvas is used to denote this
obje t type.
A olle tion of elements have been provided that an be used to onstru t
menus. A menu is a re ursive graphi al stru ture whi h is used to present
options and a tions. These hoi es an be sele ted. A menu may have as a
parent: a menubutton, a menuitem with an itemtype of as ade, a window or
a frame. A menuitem may have a menu as a parent. A menubar may have a
frame or a window as a parent. The atoms menu , menuitem , menubutton and
menubar are used to denote obje ts used to onstru t menus.
The subsystem also provides fa ilities to onstru t tables, a multi-line editor
and to sele t values from a s ale (the interfa e resembles a sliding potentiometer).

11.2.3 Events
Events are represented by tuples whi h are sent as messages to the ontrolling
pro ess. These messages have the form:

fgs , Identi er , EventType , Data , Args g
The atom gs is used to tag gs related messages. The Identi er eld ontains
either an obje t identi er returned by reate or a name (obje ts reated with
the name form of reate use names here). The EventType de nes the lass of
event that has o urred. The Data eld is used to return user de ned data
asso iated with an obje t that is generating an event. The Args eld ontains
event spe i information.
All obje ts return the following events (generi events):
A buttonpress is generated when a mouse button is pressed over an obje t.
A buttonrelease is generated when a mouse button is released over an obje t.
They both return in Args :
[ButtonNo, X, Y j ℄
An enter is generated when the mouse pointer enters an obje t area. A leave
is generated when the mouse pointer leaves an obje t. A list is returned in Args
for both these events.
1 At
2 At

the time of writing only mono hrome X11 bitmaps were supported
the time of writing GIFs and BMP image les were supported

96

CHAPTER 11.

GRAPHICS

A fo us event is generated when the keyboard fo us hanges. The Int in the
stru ture shown below is 1 if the fo us has been gained and 0 if the fo us has
been lost.
[Int j ℄

A keypress event is generated for ea h keypress. The Args eld ontains:
[KeySym, KeyCode, Shift, Control j ℄

where KeySym ontains an atom des ribing the key pressed, KeyCode ontains the key number for the depressed key and Shift and Control ontain 1 if
the modi er keys are depressed and 0 otherwise.
A motion event is generated when the mouse moves inside an obje t. The
Args eld ontains:
[X, Y j ℄

There are two obje t spe i events: li k and double- li k . The argument
lists returned for these events depend on the type of obje t that was li ked on.
11.3

Example

The program hboard.erl draws a draughts / he kers board and allows moves
to be made. Button 1 on the mouse is used to move pie es, button 2 kings
pie es, and button 3 deletes pie es. This example illustrates rubber banding
(in movement mode), the use of data elements asso iated with graphi al items,
menus, and the event driven nature of the interfa e. Sample output is shown in
gure 11.5 and the ode is shown in gure 11.6.

11.3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

EXAMPLE

97

-module( hboard).
-export([start/0℄).
start() ->
Server = gs:start(),
Win = gs: reate(window, Server, [{width, 8 * sx()},
{height, 100 + 8 * sy()}℄),
menu(Win),
Canvas = newgame(Win),
gs: onfig(Win, {map, true}),
event_loop(Win, Canvas, normal, {}).
event_loop(Win, Canvas, Mode, StateData) ->
re eive
{gs, exit, li k, _, _} ->
gs:stop(),
exit(normal);
{gs, new, li k, _, _} ->
gs:destroy(Canvas),
event_loop(Win, newgame(Win), normal, {});
{gs, Id, buttonpress, {X, Y, Base, Color, man, I},
[ 3, _, _ | _ ℄} when Mode == normal ->
gs:destroy(I),
gs: onfig(Id, [{data, {X, Y, Base, empty, empty, noimage}}℄),
event_loop(Win, Canvas, Mode, StateData);
{gs, Id, buttonpress, {X, Y, Base, Color, man, I},
[ 2, _, _ | _ ℄} when Mode == normal ->
gs:destroy(I),
pie e(Id, X, Y, Base, Color, king),
event_loop(Win, Canvas, Mode, StateData);
{gs, Id, buttonpress, {X, Y, Base, Color, Pie e, I},
[ 1, _, _ | _ ℄} when Mode == normal, Pie e =/= empty ->
gs:destroy(I),
gs: onfig(Id, [{data, {X, Y, Base, empty, empty, noimage}}℄),
event_loop(Win, Canvas, move, {Id, X, Y, Base, Color, Pie e});
{gs, Id, enter, _, _ } when Mode == move ->
gs: onfig(Id, {bg, red}),
event_loop(Win, Canvas, move, StateData);
{gs, Id, leave, {X, Y, Base, Color, Pie e, I},
_ } when Mode == move ->
gs: onfig(Id, {bg, Base}),
event_loop(Win, Canvas, move, StateData);
{gs, Id, buttonpress, {X, Y, Base, Color, Pie e, I},
[ 1, _, _ | _ ℄} when Mode == move, Pie e == empty ->
{OId, _, _, B, C, M} = StateData,
gs: onfig(Id, [{bg, Base}℄),
pie e(Id, X, Y, Base, C, M),
event_loop(Win, Canvas, normal, {});
X ->
event_loop(Win, Canvas, Mode, StateData)
end.

98
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

CHAPTER 11.

GRAPHICS

menu(Win) ->
MenuBar = gs: reate(menubar, Win, [℄),
FileBut = gs: reate(menubutton, MenuBar, [{label,
{text, "File"}}℄),
FileMenu = gs: reate(menu, FileBut, [℄),
gs: reate(menuitem, new, FileMenu, [{label, {text, "New"}}℄),
gs: reate(menuitem, exit, FileMenu, [{label, {text, "Exit"}}℄).
newgame(Win) ->
Frame = gs: reate(frame, Win, [{width, 8 * sx()},
{height, 8 * sy()}, {bw, 1}, {x, 0}, {y, 100}℄),
draw h(Frame, 8, 8),
setboard(Frame),
Frame.
setboard(Frame) ->
StartPos = [
{1, 0, white, man}, {3, 0, white,
{7, 0, white, man}, {0, 1, white,
{4, 1, white, man}, {6, 1, white,
{3, 2, white, man}, {5, 2, white,
{0, 5, bla k, man}, {2, 5, bla k,
{6, 5, bla k, man}, {1, 6, bla k,
{5, 6, bla k, man}, {7, 6, bla k,
{2, 7, bla k, man}, {4, 7, bla k,
℄,
SqLst = gs:read(Frame, hildren),
setboard(SqLst, StartPos).

man},
man},
man},
man},
man},
man},
man},
man},

{5,
{2,
{1,
{7,
{4,
{3,
{0,
{6,

0,
1,
2,
2,
5,
6,
7,
7,

white,
white,
white,
white,
bla k,
bla k,
bla k,
bla k,

man},
man},
man},
man},
man},
man},
man},
man}

setboard(SqLst, [℄) ->
true;
setboard([Sq | T℄, Pie es) ->
SqD = gs:read(Sq, data),
setboard(T, setsq(Sq, SqD, Pie es, [℄)).
setsq(Sq, SqD, [℄, L) ->
L;
setsq(Sq, {SqX, SqY, SqB, SqC, SqM, I}, [{X, Y, C, M} | T℄, L) ->
if
SqX == X, SqY == Y ->
pie e(Sq, SqX, SqY, SqB, C, M),
lists:append(T, L);
true ->
setsq(Sq, {SqX, SqY, SqB, SqC, SqM, I}, T,
[{X, Y, C, M} | L℄)
end.
draw h(Frame, Nx, Ny) ->
draw h(Frame, Nx, Ny, Nx-1, Ny-1, white).
draw h(F, Nx, Ny, 0, 0, BW) ->
sq(F, 0, 0, BW);
draw h(F, Nx, Ny, Px, 0, BW) ->
sq(F, Px, 0, BW),

11.4.

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

99

RESOURCES

draw h(F, Nx, Ny, Px-1, Ny-1, BW);
draw h(F, Nx, Ny, Px, Py, BW) ->
sq(F, Px, Py, BW),
draw h(F, Nx, Ny, Px, Py-1, opp olor(BW)).
sq(F, X, Y, Color) ->
Xs = sx(),
Ys = sy(),
gs: reate( anvas, F, [{x, X * Xs}, {y, Y * Ys},
{width, Xs}, {height, Ys}, {bg, Color},
{enter, true}, {leave, true}, {buttonpress, true},
{data, {X, Y, Color, empty, empty, noimage}}℄).
pie e(Canvas, X, Y, Base, Color, Pie e) ->
File = ase {Color, Pie e} of
{white, man} -> "whtbit.gif";
{bla k, man} -> "blkbit.gif";
{white, king} -> "whtking.gif";
{bla k, king} -> "blkking.gif"
end,
I = gs: reate(image, Canvas, [{load_gif, File}℄),
gs: onfig(Canvas, {data, {X, Y, Base, Color, Pie e, I}}).
opp olor(white) ->
bla k;
opp olor(bla k) ->
white.
sx() -> 50.
sy() -> 50.

Figure 11.6: Che ker Board Sour e Code ( hboard.erl )
11.4

Resour es

The ode les mentioned in this hapter are:
thrbut.erl
q.xbm
hboard.erl
blkbit.gif
blkking.gif
whtbit.gif
whtking.gif
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/graph.

Further information on the gs module an be found in the `The Graphi s System (GS): GS User's Guide' in `Open Tele om Platform (OTP)' do umentation

100

CHAPTER 11.

GRAPHICS

set by Eri sson Software Te hnology AB, Erlang Systems. This do umentation
is provided in HTML and Posts ript form with the Erlang distribution.
11.5

Exer ises

1. Add omments to the Che ker Board sour e ode ( hboard.erl ) from gure
11.6. Des ribe features and fun tions provided by the ode.
2. Modify the event loop in Che ker Board so that it an be easily extended
and is more readable. Pay parti ular attention to making it possible to
add new features. Suggest methods for he king the orre tness of moves.
3. Modify Che ker Board to allow two players on di erent Erlang nodes to
play against ea h other.
4. Make Wobbly Invaders ( gure 2.9) into a playable game. Only one invader
and one defender is required. Consider using a pro ess for ea h graphi al
obje t.

11.5.

EXERCISES

Figure 11.5: A game in play on the Che ker Board

101

102

CHAPTER 11.

GRAPHICS

Chapter 12

Internet

Internet based appli ations and interfa es are rapidly be oming de rigueur for
systems. Many designers hoose to use a TCP/IP based interfa e be ause of:
the simpli ity and ubiquity of the WWW interfa e; the wide availability of
the TCP/IP proto ol; and the high degree of interoperability between systems
provided by the proto ol.
The Erlang support libraries provide easy a ess to TCP/IP fun tionality,
allowing Erlang programmers to implement both lients and servers easily. This
hapter des ribes one of the library interfa es used to a ess TCP/IP so kets, the
gen t p module. Similar fun tionality for UDP or datagram so kets is provided
by the gen udp module.
12.1

Basi Fun tions

The gen t p module provides many fun tions in luding: a ept, lose, onne t, listen, re v, and send. The named fun tions are suÆ ient to setup both
lient and server programs. The fun tions are des ribed below:

a ept a epts an in oming onne tion request on a listen so ket.
lose loses an open so ket.
onne t makes a TCP/IP onne tion to a spe i ed server on a spe i ed port.
listen sets up a listen so ket to whi h lients an onne t.
re v re eives a pa ket.
send transmits a pa ket.
12.2

A Simple Web Server

WARNING: This web server des ribed in this se tion is not se ure. It per-

forms no he king on le names and hen e an be exploited by third parties to
view your les.
Figure 12.1 illustrates a simple WWW server written in Java. In this se tion
this program will be rewritten in Erlang.
103

104

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

CHAPTER 12.

INTERNET

import java.net.*; import java.io.*; import java.util.*;
// Based on TinyHttpd from Niemeyer P, Pe k J, Exploring Java,
// O'Reilly & Asso iates, 1996, pp 244-245
publi lass httpd
{
publi stati void main(String argv[℄) throws IOEx eption
{
ServerSo ket svrso k =
new ServerSo ket(Integer.parseInt(argv[0℄));
while (true)
{
So ket onso k = svrso k.a ept();
new httpd onne tion( onso k);
}
}
}
lass httpd onne tion extends Thread
{
So ket so k;
publi httpd onne tion(So ket s)
{
so k = s;
setPriority(NORM_PRIORITY - 1);
start();
}
publi void run()
{
try
{
OutputStream out = so k.getOutputStream();
PrintWriter outw =
new PrintWriter(so k.getOutputStream());
InputStreamReader inr =
new InputStreamReader(so k.getInputStream());
BufferedReader in = new BufferedReader(inr);
String req = in.readLine();
System.out.println("req " + req);
StringTokenizer st = new StringTokenizer(req);
if ((st. ountTokens() >= 2) &&
(st.nextToken().equals("GET")))
{
req = st.nextToken();
if (req.startsWith("/"))
req = req.substring(1);
if (req.endsWith("/") || req.equals(""))
req = req + "index.html";
try

12.2.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

A SIMPLE WEB SERVER

{

}
else

105

FileInputStream fin =
new FileInputStream(req);
byte [℄ data = new byte[fin.available()℄;
fin.read(data);
out.write(data);

}
at h(FileNotFoundEx eption e)
{
outw.println("404 Not Found");
}

outw.println("400 Bad Request");
so k. lose();

}

}

}
at h (IOEx eption e)
{
System.out.println("IO error " + e);
}

Figure 12.1: A Java WWW Server Implementation: httpd.java
The Erlang version an be seen in gure 12.2.
The Erlang and the Java HTTP servers take the same approa h to the task
of serving web pages. Both programs setup a listening so ket on whi h they
a ept in oming onne tions. When a onne tion request arrives it is a epted
and a new pro ess or thread is started to handle the request. The rst line of
the data sent from the web browser to the server is parsed by the pro ess or
thread and the se ond argument on the line names the le to be sent. The le
is sent to the browser and the onne tion losed.
The most notable features of the Erlang version is the duality of lists and
binaries through out the ode, and the use of regular expression routines to
perform the name manipulations.
The gen t p module allows the ontents of a stream to be seen as either a
olle tion of binary obje ts or as strings. In this implementation we have hosen
to use binary obje ts as when used in onjun tion with the le:read le fun tion it allows parti ularly easy transmission of whole les ba k to the browser.
Note that binaries must be onverted to strings for easy pattern mat hing and
manipulation.
Regular expressions are provided by the regexp module. Using the regexp:gsub fun tion it was possible to rewrite requests into an a eptable form
without using onditional statements.
Both programs have been written with larity as the primary obje tive,
rather than making maximum use of language features to redu e ode volume.
Considering this obje tive it should be noted that the Erlang version is slightly
shorter, yet fairly easy to read.

106
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

CHAPTER 12.

INTERNET

-module(httpd).
-export([start/1,server/1,reqhandler/1℄).
start(Port) ->
spawn(httpd, server, [Port℄).
server(Port) ->
{ok, Lso k} = gen_t p:listen(Port, [binary, {pa ket, 0},
{a tive, false}℄),
serverloop(Lso k).
serverloop(Lso k) ->
{ok, So k} = gen_t p:a ept(Lso k),
spawn(httpd,reqhandler,[So k℄),
serverloop(Lso k).
reqhandler(So k) ->
ReqStr = getreq(So k),
[FirstArg, Se ondArg | Tail℄ = string:tokens(ReqStr, " \n\t"),
if
FirstArg =/= "GET" ->
gen_t p:send(So k, list_to_binary("400 Bad Request\r\n"));
true ->
{ok, BaseName, _} = regexp:gsub(Se ondArg, "/$|^$",
"/index.html"),
{ok, File, _} = regexp:sub(BaseName, "^/+", ""),
sendfile(So k, File)
end,
gen_t p: lose(So k).
getreq(So k) ->
getreq(So k, [℄).
getreq(So k, OrigStr) ->
{ok, Pa k} = gen_t p:re v(So k, 0),
Re Str = binary_to_list(Pa k),
NewStr = lists:append(OrigStr, Re Str),
Pos = string:str(NewStr, "\r\n"),
if
Pos =/= 0 ->
string:substr(NewStr, 1, Pos-1);
true ->
getreq(So k, NewStr)
end.
sendfile(So k, Filename) ->
ase file:read_file(Filename) of
{ok, Binary} ->
gen_t p:send(So k, Binary);
_ ->
gen_t p:send(So k, list_to_binary("404 Not Found\r\n"))
end.

Figure 12.2: An Erlang WWW Server Implementation: httpd.erl

12.3.

107

RESOURCES

12.3

Resour es

The ode les mentioned in this hapter are:
httpd.java
httpd.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/inet.

Further information on the gen t p and gen udp modules an be found in
the `The Kernel: Kernel Referen e Manual' in `Open Tele om Platform (OTP)'
do umentation set by Eri sson Software Te hnology AB, Erlang Systems. This
do umentation is provided in HTML and Posts ript form with the Erlang distribution.
12.4

Exer ises

1. Write a lient in Erlang that an read a Web page from a server and store
the page in a le. It should have the following interfa e:
gethttp:gethttp(Url, Filename)
2. Extend the web server in gure 12.2 to handle CGI s ripts (written in
Erlang) using the GET method.
3. Extend the web server in gure 12.2 to handle CGI s ripts (written in
Erlang) using the POST method.

108

CHAPTER 12.

INTERNET

Chapter 13

Reliable Communi ations
Messages are not guaranteed to be delivered (see hapter 5). This hapter
dis usses several te hniques whi h an be used to deal with unreliable ommuni ation.
13.1

No Re overy

Sometimes it may not be desirable or possible to re over from the loss of a
message. Cir umstan es when this ould arise in lude: 

Informational messages - Some messages onvey information that is not
required for the ontinuing safe or orre t operation of a pro ess. These
messages may be dis arded. 

Timely messages - Some information has a short useful lifetime. Losing
this data may be less harmful than getting delayed data. 

Results of a fun tional onversion of data - This data an be regenerated
at any time by supplying the same set of input data. Responsibility for
re overy of this data an often be deferred to the initiator of the operation.

13.2

Ba kward Error Corre tion

Ba kward error orre tion is a family of te hniques that are used to re over data
after an error in the data has been dis overed. The basi me hanism used in
these te hniques is to retransmit data after it has been determined that an error
has o urred in the transmitted data.

13.2.1 Simple Retransmission
This retransmission me hanism is sometimes known as `Stop and Wait ARQ'
. The proto ol employs a frame number and a timeout. Figure 13.1 shows an
error free exe ution and the types of failures that this me hanism an handle.
The simple retransmission s heme relies on the initiator of a transmission
re-sending a frame if an ACK (a knowledgment) is not re eived within the
timeout. The frame number and the mat hing a knowledgment numbers are
109

110

CHAPTER 13.

RELIABLE COMMUNICATIONS

Prog A

Prog B
Frame 0
Ack 0
Frame 1
Ack 1
Frame 0

Timeout
Retransmit

Frame 0
Ack 0
Frame 1

Timeout
Retransmit

Ack 1
Frame 1
Ack 1

Discard
Duplicate
Frame

Figure 13.1: Stop and Wait ARQ
used to dis over and eliminate dupli ate transmissions. In the example only 2
frame and a knowledgment numbers are used as this is suÆ ient to dis over any
repeated transmission with at most one outstanding transmission. When this
s heme is applied in data ommuni ations a NAK (negative a knowledgment)
is often used to allow orrupted pa kets to be resent before the timeout expires.
As Erlang ommuni ations are always orre t or not present at all NAKs are
not required.
Features of the simple retransmission s heme: 

Timeout delay must be greater than the round trip time of the message
and the ACK. 

Timeout delay en ountered before re overy an o ur. 

State must be held until an ACK o urs otherwise re overy annot o ur. 

If a pro ess is ommuni ating with many other pro esses, the ommuni ation must be uniquely identi ed.

Figure 13.2 shows one implementation of this re overy me hanism. The
program in gure 13.3 and a test run in gure 13.4 show how the sawarq.erl
module an be used. The test program implements a tallier for adding up
billing re ords. Billing information should not be lost so a reliable transmission
me hanism is used to transfer the information. Re overing the total from the
tallier requires that the information be timely, so an unreliable me hanism for
transferring the data is used.

13.2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

BACKWARD ERROR CORRECTION

111

-module(sawarq).
-export([open/3, xmit/2, re v/1, pro exists/1℄).
open(Dest, Timeout, Retry) ->
RefId = make_ref(),
{Dest, RefId, 0, Timeout, Retry}.
xmit({Dest, RefId, N, Timeout, Retry}, Mesg) ->
Dest ! {self(), RefId, N, Mesg},
re eive
{RefId, N, a k} ->
{Dest, RefId, (N+1) rem 2, Timeout, Retry};
{RefId, OtherN, a k} ->
error
after Timeout ->
ase pro exists(Dest) of
true ->
re eive
after Retry ->
ok
end,
xmit({Dest, RefId, N, Timeout, Retry}, Mesg);
_ ->
error
end
end.
re v(N) ->
re eive
{Sender, RefId, N, Mesg} ->
Sender ! {RefId, N, a k},
{(N+1) rem 2, Mesg};
{Sender, RefId, _, Mesg} ->
error
end.
pro exists(Pid) when pid(Pid) ->
Nd = node(Pid),
ThisNd = node(),
ListPro = if
Nd == ThisNd ->
pro esses();
true ->
rp : all(Nd, erlang, pro esses, [℄)
end,
lists:member(Pid, ListPro );
pro exists(Name) ->
ase whereis(Name) of
undefined -> false;
_ -> true
end.

Figure 13.2: Sour e ode for implementing `Stop and Wait ARQ': sawarq.erl

112

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

CHAPTER 13.

RELIABLE COMMUNICATIONS

-module(total).
-export([start/0, read/1, add/2, tallier/2℄).
timeout() -> 10000.
retry() -> 100000.
start() ->
Pid = spawn(total, tallier, [0, 0℄),
sawarq:open(Pid, timeout(), retry()).
read(Conne t) ->
Conne tp = sawarq:xmit(Conne t, {read, self()}),
Result = re eive
X -> X
after timeout() ->
error
end,
{Conne tp, Result}.
add(Conne t, T) ->
sawarq:xmit(Conne t, {add, T}).
tallier(N, Total) ->
{Np, Msg} = sawarq:re v(N),
ase Msg of
{read, Pid} ->
Pid ! Total,
tallier(Np, Total);
{add, T} ->
tallier(Np, Total + T);
_ ->
tallier(Np, Total)
end.

Figure 13.3: Tallier: total.erl

13.3.

FORWARD ERROR CORRECTION

113

% erl
Erlang (BEAM) emulator version 4.6.4
Eshell V4.6.4 (abort with ^G)
1> P = total:start().
{<0.28.0>,#Ref,0,10000,100000}
2> {Pp, R} = total:read(P).
{{<0.28.0>,#Ref,1,10000,100000},0}
3> Ppp = total:add(Pp, 10).
{<0.28.0>,#Ref,0,10000,100000}
4> {Pppp, Rp} = total:read(Ppp).
{{<0.28.0>,#Ref,1,10000,100000},10}
5> Ppppp = total:add(Pppp, 10).
{<0.28.0>,#Ref,0,10000,100000}
6> {Pppppp, Rpp} = total:read(Ppppp).
{{<0.28.0>,#Ref,1,10000,100000},20}
7>

Figure 13.4: Testing the Tallier

13.2.2 Retransmission with Windows
The me hanism des ribed in se tion 13.2.1 works well if ommuni ation times
are short. In environments with long ommuni ation times the ACKs slow
down the proto ol. A modi ation of the proto ol allows a number of frames to
be outstanding, this set of frames is alled the window. The sender transmits
frames until he rea hes the window size. When the rst frames in the window
are a knowledged the window slides and more frames are transmitted. Frames
whi h do not get a knowledged are retransmitted. This approa h allows longer
laten ies in the response, but without ompromising the throughput as mu h
as `Stop and Wait ARQ'. These proto ols are olle tively refered to as `sliding
window' proto ols.

13.3

Forward Error Corre tion

Forward error orre tion is a family of te hniques that are used to re over data
when errors o ur. Unlike ba kward error orre tion these te hniques do not
wait for an error to be dis overed. Instead these te hniques are based on transmitting additional redundant information with the transmitted data. The redundant information is used to re onstru t the data if it is orrupted or lost.
These te hniques an be broken into two lasses. The rst lass transmits
suÆ ient data to re onstru t the lost data exa tly. The se ond lass transmits
some olle tive property of the data that an be used for approximating the lost
data. The se ond lass tends to be more ompa t, but an only be used where
an exa t representation is not required.

114
13.4

CHAPTER 13.

RELIABLE COMMUNICATIONS

Resour es

The ode les mentioned in this hapter are:
sawarq.erl
total.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/rel om.

Further information an be found on onstru ting reliable ommuni ations
on unreliable media in text books on data ommuni ations. One whi h has been
used by the author is: Stallings, W., `Data and Computer Communi ations', 4
Ed, Ma millan, 1994.
13.5

Exer ises

1. Examine the tallier in gure 13.3 for errors whi h will ause it to fail and
lose the total.
2. Using the ode in gure 13.2 as a basis write an implementation of a sliding
window proto ol with a user spe i able window size

Chapter 14

Reliability and Fault
Toleran e
Real time systems are often used in safety riti al situations { situations where
failure of the system may lead to loss of life { and situations where the timeliness of data or a tions is riti al to the ommer ial viability of a business.
In these ir umstan es the failure of a program an have drasti onsequen es.
This hapter fo uses on how reliable and fault tolerant systems an be built.
Te hniques and approa hes are introdu ed that allow systems to re ognise and
handle faults.
14.1

Terminology

A number of terms will be used in this hapter to des ribe the behavior of a
malfun tioning system:

Failure { The deviation of a system's behavior from the spe i ation
Error { An instan e of a deviation from spe i ation
Fault { The me hani al or algorithmi ause of an error
Faults an be lassi ed by their temporal hara teristi s:

Transient Fault { A fault that starts at some time, remains in the system for
a time, and then disappears from the system

Permanent Fault { A fault that starts at some time, and remains in the
system until it is repaired

Intermittent Fault { A transient fault that re urs from time to time
Failures in real time systems an be lassi ed into two modes:

Value failure { an in orre t value is returned
Time failure { a servi e o urs at the wrong time
115

116

CHAPTER 14.

14.2

RELIABILITY AND FAULT TOLERANCE

Fault Prevention

Fault prevention is divided into fault avoidan e and fault removal. Fault avoidan e fo uses on writing fault free programs. Te hniques su h as rigorous or
formal spe i ation of requirements; and the use of proven design methodologies are used to limit the introdu tion of errors into programs. Fault removal
uses ode reviews and system testing to dete t faults and remove them.
System testing is imperfe t:   

a test annot dete t the absen e of an error
realisti test onditions annot always be reated
requirements stage errors often annot be dete ted until the system is
made operational

The fun tional nature of Erlang provides the system tester with the advantage of being able to test fun tions individually. Furthermore, if fun tions have
a fun tional behavior they an be used with other fun tions and result in a
known out ome. Programming languages whi h allow state to be stored with a
fun tion or pro edure do not have this property.
14.3

Fault Toleran e

A fault tolerant system an provide either full servi e or some redu ed degree
of servi e after a fault o urs. Systems an be grouped by the degree of servi e
provided:

Full fault toleran e { no loss of servi e (either fun tionality or performan e)
in the presen e of errors

Gra eful degradation (a.k.a. Fail soft) { system ontinues to operate, but

with some level of servi e degradation, until the system either re overs or
is repaired

Fail safe { system ensures its integrity but stops delivering servi es

14.3.1 Redundan y
To provide servi e in the presen e of errors redundan y is introdu ed into the
system. Extra elements are added to the system to allow the system to re over
from faults. Redundan y an be either stati or dynami .

Stati Redundan y
Parts of the system are repli ated in order to ontinue to provide servi e in the
event of the failure of a repli ated omponent.
Triple Modular Redundan y (TMR) is a spe ial ase of N Modular Redundan y (NMR). N Modular Redundan y (see gure 14.1) repli ates a system N
times and employs a voting system to determine the result given. The repli ated systems are not permitted to intera t with ea h other. This approa h
an lead to a less reliable system as it in reases the omplexity of the system

14.3.

117

FAULT TOLERANCE

Input

Inputs

Vers
1

Vers
2

Vers
N
...

Voting
System

Output
Driver

Figure 14.1: N Module Redundan y

118

CHAPTER 14.

RELIABILITY AND FAULT TOLERANCE

and the voting s heme may introdu e errors ( ommon problems in lude failures
in syn hronisation and failures in omparisons). Ea h of the versions of the
program must di er in some way su h that the faults in one version are not
related to faults in another version. This di eren e may be a hieved through
using di erent development teams, di erent algorithms, or di erent ompilers.
The driver provides both the required inputs and ompares the results returned by the versions. Two typi al implementations of the driver pro ess exist.
The simpler implementation if for one-shot operations. In this implementation,
the driver invokes ea h pro ess, wait for results and a ts on the results. The
more omplex implementation allows for ontinuous operation. Continuous intera tion is a hieved by invoking the pro esses, providing inputs as required,
olle ting results when omparison points are rea hed, and generating a tions.
As al ulation errors an a umulate in some systems leading to orre t programs diverging, some implementations may resyn hronise the state of the versions at the omparison points to ensure that any divergen e in results is due
to a fault in the system rather than a umulated al ulation errors.
The time between omparisons (the granularity of the omparison pro ess)
is signi ant as a longer period tends to in rease the divergen e of the results returned by ea h version. However, a shorter period results in in reased overhead
asso iated with the olle tion of results from ea h of the versions.
Another in uen e on the time between omparisons is the required a ura y
of a result and the rate a result is required. There is a lass of numeri al
algorithms alled iterative te hniques. These algorithms take an approximation
of a value and perform an operation on the value to improve the approximation.
The number of iterations and the quality of the initial guess determine the
rate at whi h the approximation onverges with the real target value. Too few
iterations results in a wide varian e from the desired target. Too many iterations
may return a result more a urate than required wasting ma hine y les.
The method of vote omparison is riti al to the implementation of NMR.
Where results are integers or strings, omparisons are a straight forward matter
of omparing votes and returning the majority de ision. Comparing oating
point (real) values is more omplex.
Measurements of real systems usually return results whi h are more a urately represented than measured. This typi ally results in a spread of results
being returned for the same real result measured. Although two al ulations
may be equivalent in exa t arithmeti , their results may di er when performed
with the nite arithmeti used to express oating point numbers. Thus a spread
of results is also possible when di ering algorithms and implementations are used
to perform al ulations using oating point numbers.
One te hnique used for omparing oating point numbers is to ompare
values with a threshold and use the result of this omparison to return a symboli result whi h an be used in an exa t voting s heme (see gureinexa t).
This method performs well when the inexa t results are not near the threshold.
When results are lose to the threshold (within the error in the al ulation or
measurement) the symboli result is unreliable. Adding a toleran e to the result
does not solve the problem, it merely moves the unreliability from results about
the threshold value to results near the toleran e values (see gureinextol).
With vote omparison based on inexa t data disagreement is possible without the event of an error.

14.3.

119

FAULT TOLERANCE

Output
1 0

Measurements

Result
1

Threshold

?

0

Figure 14.2: Inexa t Comparisons of Measured Data

Output
1 0

Measurements

Result
1

$+\Delta$
Threshold
$-\Delta$

?
Unknown
?
0

Figure 14.3: Inexa t Comparisons of Measured Data { with Toleran e

120

CHAPTER 14.

RELIABILITY AND FAULT TOLERANCE

Dynami Redundan y
Stati redundan y dupli ates omponents that are used regardless of whether a
fault has o urred or not. In dynami redundan y, the redundant omponents
are only used when a fault has been dete ted.
The dynami ally redundant te hnique for implementing a fault tolerant system introdu ed here onsists of four phases: error dete tion, damage on nement and assessment, error re overy, and fault treatment and ontinued servi e.
Error dete tion is riti al to the su ess of fault toleran e as the majority of
faults eventually lead to errors and no fault tolerant s heme an operate until
an error is dete ted.
Environmental dete tion of errors relies on the environment in whi h a program exe utes to alert the program to a failure. Erlang uses error trapping,
at h and linked pro esses to report the errors des ribed in se tion 8.1. Other
languages rely on the operating system to generate ex eptions (in Unix these
are alled signals) when a program ex eeds the restri tions provided by the
environment.
In the appli ation dete tion approa h an appli ation dete ts errors itself.
Some te hniques whi h an be used in lude: 

Repli ation Che ks { Use of NMR to ompute and ompare results. Typi ally 2 versions are used and a disagreement indi ates a fault. 

Timing Che ks: Wat h Dog Timer { A timer is asso iated with a omponent. The timer is reset on orre t intera tions with the omponent. If
the timer expires the omponent is assumed to be in error. This is related
to a heart beat . A omponent uses a timer to trigger periodi signals to a
pro ess monitoring it. Failure of these signals to arrive indi ates an error
in the omponent. 

Timing Che ks: Deadlines { Where timely response is required, missing a
deadline is an error. 

Reversal Che ks { Where there is a one to one relationship between the
inputs and the outputs of a omponent, an output value an be used to
ompute the value of the input. Comparing the input with the al ulated
value allows the operation of the omponent to be he ked. 

Error Dete ting Codes { The integrity of data an be he ked by using
an error dete ting ode to provide redundant data. Common examples
in lude he ksums and parity. 

Reasonableness Che ks { Using knowledge of the design and onstru tion
of the system, programmers an onstru t tests that values or the state of
the system are reasonable. These tests an be subsetted into: onsisten y
tests whi h he k that related values fall within the expe ted relationship;
and onstraint tests whi h he k that values fall inside an expe ted set of
values. These tests an either be expli itly oded or impli itly represented.
In C these test are often expli itly oded as assertions. Types and subtypes
an be used in Ada to impli itly ode an expe ted set of values. In Erlang,
reasonableness he ks are typi ally expli itly oded with no additional
language support.

14.3.  

FAULT TOLERANCE

121

Stru tural Che ks { The integrity of data stru tures su h as lists, queues
and trees an be he ked by adding redundant information to the stru ture. Common methods are to in lude element ounts or redundant pointers. Erlang does not support the se ond method as it does not support
pointers.

Dynami Reasonableness Che ks { The output from a omponent an
be related to previous outputs from a omponent. If there is a relationship between onse utive outputs a bound an be pla ed on the di eren e
between ea h output. If the outputs are too dissimilar an error an be
assumed to have o urred.
Only some of the te hniques may be feasible or useful in a given situation or
program.
The damage on nement and assessment phase o urs after an error has
been dete ted. This phase assesses how orrupt the system has been made by
the error. Fa tors involved in this assessment are: the type of error en ountered,
the period of time between the fault o urring and the error being dete ted, and
how well the system ontains the spread of an error.
Design te hniques are used to on ne damage. Interfa es an test data
passed to them to ensure reasonableness and ontain errors. A modular de omposition de nes a set of interfa es through whi h information is passed. Data
transfers whi h avoid these interfa es should be eliminated. In Erlang these
data transfers would take pla e as either: messages sent dire tly rather than
using a fun tion provided by a module to orre tly format the message; or, dire tly a essing a data stru ture passed ba k by a fun tion when the module
has fun tions for manipulating the data stru ture. The de ned set of interfa es
eases the task of determining the impa t of an error. Implementing shifts from
one onsistent state to another onsistent state using atomi a tions an on ne
an error to a single pro ess or state within a pro ess.
Error re overy is performed after the damage has been assessed.
Forward error re overy attempts to take a system from a damaged state into
a orre t state by applying orre tions to sele ted elements of the system state.
Ba kward error re overy te hniques restore a system to a safe state before
the error o urred and an alternative se tion of the program is then exe uted.
Che kpointing is a te hnique where the system state is stored. These re overy points an then be used to restore the system state if an error is dete ted.
Storing the whole system state an be expensive or impra ti al. In remental
he kpointing an be used to redu e the ost by storing only the hanges in
state from a stable state. Where multiple pro esses are employed are must be
taken to ensure that the he kpoints used give a onsistent state for the whole
system, where pro esses have ommuni ated it may be ne essary to undo the
e e t of the ommuni ation.
Although error re overy has removed the fault from the system, the possibility of the fault re urring exists. Fault treatment and ontinued servi e is
on erned with removing the ause of the fault. Logging should be used to provide information to lo ate the fault and the omponent should be repaired to
prevent the fault re urring. Unlike many other languages Erlang is well suited
to fault repair as its ode modules an be repla ed on the y (see hapter 9).
In se tion 14.3.1 the driver was introdu ed as an implementation of stati
redundan y. The re overy blo k approa h will be introdu ed as an approa h to

122

CHAPTER 14.

RELIABILITY AND FAULT TOLERANCE

implementing dynami redundan y. The approa h is a ba kward error re overy
te hnique. Re overy blo ks an be nested. The te hnique is illustrated as a ow
hart in gure 14.4

Establish
Recovery
Point
NRec=1

Select
NRec
1
Alternative 1

2

N

Alternative 2

Accept
Yes
Discard
Recovery
Point

...

Alternative N

No
NRec=NRec+1

NRec<=N

Yes

No
Exit

Fail

Figure 14.4: Algorithm for Re overy Blo ks
The essen e of the re overy blo k approa h is to save a re overy point and
try a series of implementations until the a eptan e test is met. It is important
to note that an a eptan e test is used not a orre tness test. The test is present
to ensure the stability of the system not to test the orre tness of the system.
14.4

When Re overy is Undesirable

There are some ir umstan es when re overy is not desirable in these ases
the re overy a tion either ompli ates the system without providing gain, or
re overy would ome too late to be of bene t. An example of this is the failure
of a telephone ex hange. Attempting to restore the alls that were present at the
time of the failure is diÆ ult as the phone users who were ut o are probably

14.5.

123

RESOURCES

not expe ting to have their alls restored. Thus a lot of work would be done
for people who no longer require the servi e. It should be noted that within
this system there are still omponents that would require re overy. The billing
system is an example of this as the owner of the ex hange wants to be paid for
the servi e provided to the phone users.
14.5

Resour es

The ode les mentioned in this hapter are:
exrev1.erl
exrev2.erl
These les an be retrieved from:
http://www.ser .rmit.edu.au/~mauri e/erlbk/eg/relflt.

Further information on the topi s dis ussed in this hapter an be found in
Burns, A., Wellings A., `Real-Time System and Programming Languages', 2 ed,
Addison Wesley Longman 1997.
14.6

Exer ises

1. Devise a real time system where there are several algorithms whi h are
appli able to solving the same problem.
2. Implement a driver pro ess in Erlang for the system you devised.
3. Implement re overy blo ks in Erlang for the system you devised.
4. Dis uss the advantages and disadvantages of driver pro esses and re overy
blo ks.
5. Examine the fun tions in gure 14.5 determine if they are suitable for a
reversal he k and if possible design a reversal he k for it.
1
2
3
4
5

-module(exrev1).
-export([f/1℄).

1
2
3
4
5

-module(exrev2).
-export([f/1℄).

f(X) ->

f(X) ->

1 + math:sqrt(X).

0.8 * math: os(X).

Figure 14.5: exrev1.erl and exrev2.erl

124

CHAPTER 14.

RELIABILITY AND FAULT TOLERANCE

Index
(, 64
), 64
*, 11
+, 11
,, 18
-, 11
., 18
/, 11
;, 18, 36
?:, 35
#, 10
$, 10
%, 6, 85
, 37
j, 13

bindings, 1, 15
bit stuÆng, 59
bor, 11
bound, 35
bsl, 11
bsr, 11
built in fun tion, 20
button, 94
buttonpress, 95
buttonrelease, 95
bxor, 11

abnormal, 63
a ept, 103
ACK, 109
after, 48
all loaded, 80
append, 33
appli ation dete tion, 120
apply, 53
ar , 95
arity, 2
ARQ, 109
assertion, 120
assign, 1, 6
atom, 9, 11
atom to list, 15
atomi a tion, 121
attribute, 19, 85, 88

allba k fun tion, 74
anvas, 95
ase, 35, 36, 58
ase lause, 66
at h, 63, 64, 67, 72
at h all, 36, 37, 48
he kpoint, 121
hoi e, 35
lause, 7
li k, 96
lose, 103
ode repla ement, 19, 77, 78, 121
omment, 6, 85
omment onvention, 85
onne t, 103
onsisten y tests, 120
onstant, 10
onstraint tests, 120
onstru tion, 27
onvention, 85
reate, 95

ba kward error orre tion, 109
ba kward error re overy, 121
badarg, 66
badarith, 66
badmat h, 66
band, 11
BIF, 20

damage assessment, 121
damage on nement, 121
data types, 9
deadline, 120
de laration, 19
de larative, 23
default behavior, 63
125

126
defensive programming, 70, 72
delete, 79
distribution, 48
div, 11
double- li k, 96
dynami link, 77
dynami reasonableness he ks, 121
dynami redundan y, 120
element, 12, 13
enter, 95
entry, 95
environmental dete tion, 120
erase, 45
erl, 1
error, 115
error dete ting odes, 120
error dete tion, 120
error handler, 69
error re overy, 121
event model, 91
events, 95
ex eption, 63
exit, 67, 70, 72
exit trapping, 72
export, 2, 19
fail safe, 116
fail soft, 116
failure, 63, 115
fault, 115
fault prevention, 116
fault toleran e, 116
fault treatment, 121
atten, 31
oat, 9, 10
oat to list, 15
fo us, 95
forward error orre tion, 113
forward error re overy, 121
frame, 95
full fault toleran e, 116
fully quali ed name, 20, 77
fun tion, 6, 17, 77
fun tion body, 6
fun tion head, 6, 37, 58
fun tion lause, 66
garbage olle tion, 17
gen server, 74

INDEX

gen t p, 103
gen udp, 103
generi events, 95
generi servers, 74
get, 45
get keys, 45
gra eful degradation, 116
graphi s, 91
graphi s obje ts, 94
gs, 91
gs: on g, 92, 94
gs: reate, 92, 93
gs:destroy, 94
gs:read, 94
gs:start, 92, 93
gs:stop, 92, 93
guard, 18, 23, 35, 37
hashable, 58
hd, 15
HDLC, 59
heart beat, 120
if, 35, 36, 58
if lause, 66
image, 78, 95
import, 19
in remental he kpointing, 121
integer, 9, 10
integer to list, 15
intermittent fault, 115
io, 18
IPC, 43
is loaded, 80
iterative te hniques, 118
Java, 1
keypress, 96
label, 94
last all optimisation, 57
length, 15, 27
library, 103
line, 95
link, 70, 72, 77
linked pro esses, 70
list, 9, 13
list to atom, 15
list to oat, 15
list to integer, 15

127

INDEX

listbox, 95
listen, 103
load le, 79
logi al-and, 18
map, 53
mat h, 63
memory management, 17
menu, 95
menubar, 95
menubutton, 95
menuitem, 95
message, 18, 45, 109
meta-programming, 53
modular de omposition, 121
module, 2, 19, 20, 77, 78
module attribute, 88
motion, 96
NAK, 109
name, 48
NMR, 116
no at h, 66
non-lo al return, 67
nopro , 66
oval, 95
pattern, 7
pattern mat h, 48, 58, 63
pattern mat hing, 7, 12, 23, 35
permanent fault, 115
pid, 9, 11, 43, 48, 51, 67
polygon, 95
pre ondition, 70
prime number, 41
pro edural, 23
pro ess, 43
pro ess di tionary, 18, 45
pro ess ag, 72
proper list, 13
purge, 79
put, 45
pxw, 91
reasonableness he ks, 120
re eive, 48
re overy blo k, 121
re overy point, 121
re tangle, 95
re ursion, 6, 23

re v, 103
Redu tion, 27
redundan y, 116
referen e, 9, 12
register, 51
registered name, 72
registered names, 51
reliable ommuni ation, 109
rem, 11
repli ation he ks, 120
retransmission, 109
reversal he k, 120
robust program, 63
s ope, 15
self, 48
self(), 43
semaphore, 85
send, 103
shell, 1
side e e t, 17
Sieve of Eratosthenes, 41
signal, 67, 70
single assignment, 15, 35
sliding window, 113
sname, 48
soft purge, 79
spawn, 48
spawn link, 70
sta k, 57
stati linking, 77
stati redundan y, 116
Stop and Wait ARQ, 109
stru tural he ks, 121
system testing, 116
t p/ip, 103
term, 9
terminate, 67
test before use, 70
text, 95
throw, 63, 64
time delay, 48
time failure, 115
timeout value, 66
tl, 15
TMR, 116
Transformation, 27
transient fault, 115
trapping exits, 72

128
triple modular redundan y, 116
try and re over, 70
tuple, 9, 12
unbound, 66
undef, 67
unde ned fun tion, 69
unde ned global name, 69
unlink, 70
unregister, 51
value failure, 115
variable, 15
variables, 6
vote omparison, 118
wat h dog timer, 120
well formed list, 13
when, 48
whereis, 51
window, 94

INDEX

Glossary
ACK A knowledgment
ARQ Automati repeat request
Arity Number fundamentally asso iated with an entity. In Erlang, the arity
of a fun tion is its number of arguments

Atom a onstant name
BIF are members of a spe ial lass of fun tions known as Built In Funtions.

These fun tions are built in to the interpreter in an interpreted environment.

BST Binary Sear h Tree
Ba kward Error Corre tion re overs data by having the transmitter re-send
lost or orrupted data

Ba kward Error Re overy A lass of error re overy te hniques that restore

a system to a safe state before the error o urred and exe ute an alternative se tion of the program

Binding The asso iation of a variable name to the ontents of the variable.
Cat h all mat hes any pattern.
Convention A onvention is an agreed means for handling a spe i ed ir um-

stan e. It need not be enfor ed and may be arbitrary in nature. The
general use of onventions in programming is to improve the readability
and understandability of ode.

Elements the items that a tuple or list are onstru ted from
Erlang Shell An environment whi h allows users to dire tly intera t with Erlang fun tions

Error An instan e of a deviation from spe i ation
Fail safe System ensures its integrity but stops delivering servi es
Fail soft see gra eful degradation
Failure The deviation of a system's behavior from the spe i ation
Fault The me hani al or algorithmi ause of an error
129

130

Glossary

Float a number with a fra tional part (ie. no de imal point)
Forward Error Corre tion re overs data by augmenting the data from the

transmitter with additional data that an be used to re onstru t lost or
orrupted data

Forward Error Re overy A lass of error re overy te hniques that attempt

to take a system from a damaged state into a orre t state by applying
orre tions to sele ted elements of the system state

Full fault toleran e No loss of servi e (either fun tionality or performan e)
in the presen e of errors

Fully quali ed name onsists of the module name a olon and the fun tion
name.

Gra eful degradation System ontinues to operate, but with some level of
servi e degradation, until the system either re overs or is repaired

Granularity Size of an element or omponent of a al ulation
IPC Inter-Pro ess Communi ation
Indu tion a pro ess of onstru ting a general result for a given problem from
a given set of fa ts relating to the problem

Integer a positive or negative number with no fra tional part (ie. no de imal
point)

List a variable length olle tion of elements
NAK Negative a knowledgment
NMR N Modular Redundan y
Pid a pro ess identi er
Pro ess Di tionary A pro ess's private asso iative store
Proper list a proper list has an empty list ([℄) as its last element
Re ursion A fun tion whi h alls itself or alls a fun tion or series of fun tions
whi h all the original fun tion

Redundant Additional omponent whi h does not ontribute to normal operation

Referen e a unique value that an be opied or passed but annot be generated
again

S ope the s ope of an entity is the se tion of program in whi h an entity an
be a essed or named.

Side E e t an intera tion between a fun tion and its environment other than
through its input parameters or its output value

Single assignment a variable may be assigned (bound) exa tly on e

Glossary

131

Stati Redundan y Repli ation of a omponent or servi e
TMR Triple Modular Redundan y
Term A value. An integer, oat, atom, pid, referen e, list, or tuple and any of
list or tuple omposed of these types

Tuple a xed length olle tion of elements
Well formed list a well formed list has an empty list ([℄) as its last element