Exercises
Exercises
2 Sequential Programming 6
2.1 Evaluating Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2 Creating Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Side Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.4 Database Handling Using Lists . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.5 ADVANCED: Manipulating Lists . . . . . . . . . . . . . . . . . . . . . . . . 8
2.6 ADVANCED: Implement Quicksort and Merge sort . . . . . . . . . . . . . . 9
2.7 ADVANCED: Database Handling using Trees . . . . . . . . . . . . . . . . . 9
3 Concurrent Programming 10
3.1 An Echo Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2 The Process Ring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 The Process Crossring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
7 Advanced Topics 20
7.1 ADVANCED: List Comprehensions . . . . . . . . . . . . . . . . . . . . . . . 20
7.2 Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
7.3 Distributed, Replicated Associative Store . . . . . . . . . . . . . . . . . . . 21
Unix Shell
$ erl
Erlang Shell Session
Eshell V8.3 (abort with ˆ G)
1>
A. Erlang expressions
1 + 1.
[1|[2|[3|[]]]].
A = 1.
B = 2.
A + B.
A = A + 1.
L = [A|[2,3]].
[[3,2]|1].
[H|T] = L.
B = = 2.
B = 2.
2 = B.
B = C.
C = B.
B = C. (repeat it now that C is bound).
1.2.2 Atom
An editor with easy to learn interface, large amount of convenience plugins and multiple
languages supported. Supports both Erlang and Elixir. Windows, Mac OS X and Linux
all are supported.
After installation, proceed to the Options ⇒ Plugins, and there find Erlang or Elixir.
https://atom.io/
1.2.3 Emacs
An Erlang mode for Emacs exists. Detailed instructions on how to setup the erlang-mode
on a UNIX or Windows machine are available at:
http://www.erlang.org/doc/apps/tools/erlang_mode_chapter.html
You can also install the erlang-mode for Emacs using a MELPA package:
http://melpa.milkbox.net/#/erlang
The standard erlang-mode for Emacs provides basic functionalities such as syntax high-
lighting, indentation and in-module code navigation. For more advanced features you may
want to look at the Erlang Development Tool Suite (EDTS):
https://github.com/tjarvstrand/edts
Hint:
5 * (F - 32) = 9 * C
Part B
Write a function temp:convert(Temperature) which combines the functionality of
f2c and c2f. A usage example follows:
Erlang Shell Session
Eshell V8.3 (abort with ˆ G)
1> temp:convert({c, 100}).
{f, 212.0}.
2> temp:convert({f,32}).
{c,0.0}.
P Q P and Q P or Q
false false false false
false true false true
true false false true
true true true true
A third operator, called not, will simply reverse the input it has received: not true
will return false and not false will return true.
Write a module boolean.erl that takes logical expressions and boolean values (rep-
resented as the atoms true and false) and returns their boolean result. The functions you
should write should include b_not/1, b_and/2 and b_or/2. You may not use the
logical constructs and, or or not. Test your module from the shell.
b_not(false) → true
b_and(false, true) → false
b_and(b_not(b_and(true, false)), true) → true
Note:
foo(X)→Y means that calling the function foo with the parameter X will
result in the value Y being returned.
Note:
2 Sequential Programming
These exercises will get you familiar with recursion and its different uses. Pay special
attention to the different recursive patters that we covered during the lectures. If you are
having problems finding bugs or following the recursion, try using the debugger.
sum(5) → 15.
Part B
Write a function sum_interval/2 which given two integers N and M, where N =<M,
will return the sum of the interval between N and M. If N >M, you want your process to
terminate abnormally.
sum_interval(1,3) → 6.
sum_interval(6,6) → 6.
create(3) → [1,2,3].
Part B
Write a function reverse_create/1 which returns a list of the format [N, N-1,..,2,1].
reverse_create(3) → [3,2,1].
Hint:
Part B
Write a function even_print/1 which prints out the even integers between 1 and N.
Erlang Shell Session
Eshell V8.3 (abort with ˆ G)
1> even_print(5).
2
4
ok
Hint:
Use guards
Hint:
Use lists and tuples as your main data structures. When testing your pro-
gram, remember that Erlang variables are single assignment. The order of the
list will be implementation dependent so you may not get the same order as
shown in the example.
db:new() → DbRef.
db:destroy(DbRef) → ok.
db:write(Key, Element, DbRef) → NewDbRef.
db:delete(Key, DbRef) → NewDbRef.
db:read(Key, DbRef) →{ok, Element} | {error, instance}.
db:match(Element, DbRef) → [Key1, ..., KeyN].
Note:
filter([1,2,3,4,5], 3) → [1,2,3].
Part B
Write a function which given a lists will reverse the order of the elements.
reverse([1,2,3]) → [3,2,1].
Part C
Write a function which, given a list of lists, will concatenate them.
Hint:
You will have to use a help function and concatenate the lists in several
steps.
Part D
Write a function which given a list of nested lists, will return a flat list.
Hint:
Quicksort
The head of the list is taken as the pivot; the list is then split according to those elements
smaller than the pivot and the rest. These two lists are then recursively sorted by quicksort
and joined together with the pivot between them.
Mergesort
The list is split into two lists of (almost) equal length. These are then sorted separately
and their result merged together.
Hint:
Note:
Make sure you save a copy of your db.erl module using lists somewhere
else (or with a new name) before you start changing in.
3 Concurrent Programming
These exercises will help you get familiar with the syntax and semantics of concurrency
in Erlang. You will solve problems that deal with spawning processes, message passing,
registering, and termination. If you are having problems finding bugs or following what is
going on, use the process manager.
echo:start() → ok.
echo:stop() → ok.
echo:print(Term) → ok.
Hint:
Warning:
Use an internal message protocol to avoid stopping the process when you
for example call the function echo:print(stop).
Hint:
There are two basic strategies to tackling your problem. The first one is to
have a central process that sets up the ring and initiates the message sending.
The second strategy consists of the new process spawning the next process in
the ring. With this strategy you have to find a method to connect the first
process to the last.
my_db:start() → ok.
my_db:stop() → ok.
my_db:write(Key, Element) → ok.
my_db:delete(Key) → ok.
my_db:read(Key) → {ok, Element} | {error, instance}.
my_db:match(Element) → [Key1, ..., KeyN].
Hint:
Use the db.erl module as a back end and use the server skeleton from the
echo exercise.
Erlang Shell Session
Eshell V8.3 (abort with ˆ G)
1> my_db:start().
ok
2> my_db:write(foo, bar).
ok
3> my_db:read(baz).
{error, instance}
4> my_db:read(foo).
{ok, bar}
5> my_db:match(bar).
[foo]
mutex:start() → ok.
mutex:wait() → ok.
mutex:signal() → ok.
Hint:
The difference in the state of your FSM is which messages you handle in
which state.
my_db_trans:lock() → ok.
my_db_trans:unlock() → ok.
The file fussball.erl contains a program similar to the ping pong program, i.e. it
sends a message back and forth between two processes, only in a slightly more entertaining
fashion.
An example of how to run the code follows:
Modify the code from the Fussball exercise to make the processes trap exits. Do this
by inserting the following line first in the init function:
process_flag(trap_exit, true),
Exit signals will now be added to the message queue instead of terminating the pro-
cesses. To make the processes print out the exit signals they receive, add the following
receive clause to the loop function:
{’EXIT’, _Pid, Reason} ->
io:format("Got exit signal: ~p~n", [Reason]);
Find a way to link both countries together in the init phase so that whenever one of
the countries is stopped, the other also is.
Hint:
Linking to a non-existing process causes an exception. You should handle
that.
Hint:
Use catch link(Pid) in case Pid terminated before its request was
handled.
Hint:
Make your supervisor start the mutex and database server processes. Note
that you have to pass the function and arguments used in the spawn function,
and not the start function. That might result in your process not getting
registered.
Note:
SupName | Pid means you should be able to pass either the atom by
with the supervisor process is registered by, or the Process ID returned when
the supervisor is started.
Hint:
Use the following record definition: -record(data, {key, value}).
Note:
Make sure you save a copy of your db.erl module using lists somewhere
else (or with a new name) before you start changing in.
Hint:
Use lists:seq(1, N).
Part B
Using funs and higher order functions, write a function which given a list of integers and
an integer, will return all integers smaller than or equal to that integer.
Part C
Using funs and higher order functions, write a function which prints out the even integers
between 1 and N.
Hint:
Solve your problem either in two steps, or use two clauses in your fun.
Part D
Using funs and higher order functions, write a function which, given a list of lists, will
concatenate them.
Part E
Using funs and higher order functions, write a function that given a list of integers returns
the sum of the integers.
Hint:
Use lists:foldl, and try figure out why we prefer to use foldl rather
than foldr.
7 Advanced Topics
These exercises will make you familiar with issues covered in the advanced topics section.
In many cases, you will be using exercises created in the previous section, making the
programs more robust or adding to their functionality.
Example:
[3,6,9]
Part B
Using list comprehensions remove all non integers from a polymorphic list. Return the list
of integers squared.
Example:
Part C
Using list comprehensions and given two lists, return a new list which is the intersection
of the two lists.
Example:
Hint:
Part D
Using list comprehensions and given two lists, return a new list which is the disjunction of
the two lists.
Example:
Hint:
7.2 Distribution
Make your server from exercise ?? (??) a distributed one. Clients should, through the
functional interface, be able to query the node from any distributed Erlang node sharing
the same cookie. Using a macro, you may hardcode the node name of the server.
Sending queries on an open network means there is a risk of interference from a third
party. Add references in the message protocol between the client and the server, to ensure
that you are in fact receiving the reply to that query, and not just any message following
the protocol.
The node on which the server is running may be down or may crash just after you
have sent your request. Ensure that these cases are handled, and that you return an error
should they occur.