Sequential Erlang

Mandatory assignment

File to use

Open the file module-8/src/tutorial.erl in a text editor.

Emacs is the de facto standard editor for Erlang and provides syntax highlighting and automatic indentation and is highly recommended but similar support is provided by many other code editors.

First compile

In the terminal, navigate to the module-8 directory and use make to compile all modules.

$ make

You may now see a number of warnings about unused variables. This is expected and the warnings will disappear after you completed all the steps in this tutorial and the other exercises.

Read the module html documentation

You should already have generated html documentation for all the provided Erlang modules.

From the documentation menu, chose the tutorial module. On this page you find documentation for all the exported functions in the tutorial.erl module. Briefly read through the documentation to familiarize yourself with exported functions and their expected behaviors.

Calling functions

If in module test.erl the function double/1 is defined.

double(A) -> 2*A.

Within module test.erl, all functions are accessible directly. When defining the function four/0 in test.erl the function doulbe/1 can be called directly.

four() -> double(2).

Only exported functions can be called from the Erlang shell or from other modules. To call a function defined in a module the following syntax must be used.

Module:Function(Arguments).

To call double/1 defined in the test.erl module form the Erlang shell or from another module.

test:double(2).

The Erlang shell

From the terminal, navigate to the module-8/src directory.

$ cd module-8/src

This is the directory for all the module source files. Now, start a new Erlang shell.

$ erl

You should see something similar to:

Erlang R15B03
(erts-5.9.3)
[source] [64-bit] [smp:2:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.3 (abort with ^G)
1>

Note that the Erlang shell prompt now is 1>. Add two numbers.

1> 1 + 3.
4
2>

After the result is printed, the new 2> prompt is printed. The Erlang shell prompt counts the number of evaluated expressions. 4 2> 1> is the Erlang shell prompt. The number 1

After the result is printed, the new 2> prompt is printed. The Erlang shell prompt counts the number of evaluated expressions.

The Erlang shell prompt

4 In all remaining instructions erlang> will be used to denote the Erlang shell prompt.

Compile from the Erlang shell

If you compile using the Makefile, the new versions of the compiled modules (the beam files) will not be automatically available in any existing Erlang shells. If you are interesting in more details, read more here. When testing individual modules manually from the Erlang shell it is more convenient to compile from the Erlang shell.

You now can compile individual modules directly from the Erlang shell using the c/1 function:

erlang> c(tutorial).

After a number of warnings about unused variables you should get the following ok message.

{ok,tutorial}
erlang>

Test function from the Erlang shell

Execute the hello/0 function, don’t forget the trailing ling period .:

erlang> tutorial:hello().

The hello/0 function simply prints Hello!.

Hello!
ok

Quit the Erlang shell

To quit the Erlang shell, type q(). and press enter.

erlang> q().

You should now get back the Linux terminal prompt.

Beam files

From the Linux terminal:

$ ls | grep tutorial
tutorial.beam
tutorial.erl

Note

When compiling form the Erlang shell, the resulting beam file is saved in the current working directory.

From the Linux terminal, delete all beam files in the module-8/src directory:

$ make clean

Start the Erlang shell

In the Linux terminal, from the module-8/src directory, start the Erlang shell.

$ erl

Recursion

Erlang is a functional language and recursion is the fundamental concept used to achieve loop-like constructs. Have a look at the tutorial:hello/1 function. What do you think will happen when we call tutorial:hello(4)?

Todo

Make a dry run of tutorial:hello(4) on a piece of paper.

From the Erlang terminal:

erlang> tutorial:hello(4).

Did your pen and paper dry run match? Next, look at the tutorial:fac/1 function. This is the straight forward recursive implementation of the factorial function:

erlang> tutorial:fac(7).

This will return 7!, i.e., 5040.

EDoc

Todo

Add a proper EDoc description of tutorial:hello/1 by changing the text after the @doc tag.

Update the generated html documentation:

$ make doc

Refresh your web browser and make sure you can see the new description of tutorial:hello/1.

To be implemented

In the tutorial module, the atom tbi (short for To Be Implemented) is used as a place holder. You must replace all the tbi atoms with Erlang code to get working solutions.

Tail recursion

Todo

Write a tail recursive version of the factorial function by completing the tutorial:fac_tr/2 function.

Verify your solution by compiling from the Linux terminal and testing from the Erlang shell.

List comprehensions

Todo

In the tutorial:right_triangle/1 function, use a list comprehension to return a list of tuples {A, B, C} such that A and B are sides in a right triangle with hypotenuse C, where A, B, C <= N.

By calling the tutorial:simpsons/0 function, a list of members of the Simpson family is returned. We want to filter this list to obtain new lists.

Todo

In the tutorial module, use list comprehensions to complete the implementations of simpsons/1.

For example, to get a list of all all the names in the family:

erlang> tutorial:simpsons(names).
["Bart","Snowball II","Homer","Lisa", "Santa's Little Helper","Marge","Spider Pig"]

For example, to get a list of all the pets:

erlang> tutorial:simpsons(pets).
["Snowball II","Santa's Little Helper","Spider Pig"] 

Guarded functions

Function heads can have guards. This is a convenient way to handle various cases when defining a function. To get the ASCII value of a character, simply prefix the character with $. For example, to get the ASCII value of the character A from the Erlang shell:

erlang> $A.
65

Todo

Complete the char_to_upper/1 and char_to_lower/1 functions. Use guarded function heads to check if the argument character is within range.

Test your solution:

erlang> tutorial:char_to_upper($b).
66

Note that char_to_upper/1 takes a ASCII value as argument and returns a ASCII value. In the above example, $b = ASCII(b) = 98 is used as argument and 66 = ASCII(B) is returned.

Map

Strings in Erlang are simply list of ASCII values, for example:

[$E, $r, $l, $a, $n, $g] = [69, 114, 108, 97, 110, 103] = "Erlang"

Todo

Complete the str_to_upper/1 and str_to_lower/1 functions by using the lists:map/2 function together with the char_to_upper/1 and char_to_lower/1 functions.

List comprehensions

You could also use list comprehensions to implement str_to_upper/1 and str_to_lower/1.

Fold

A common pattern is to recombine the elements of a data structure to form a new data structure, often this is referred to as folding a data structure into a new data structure. One example of a fold is when the elements of a list is recombined into a single value. The Erlang lists:foldl/3 function does exactly this.

Todo

  • Complete the max/1 function by binding F to an anonymous function.
  • Complete the count/2 function by binding F to an anonymous function.
  • Complete the odd_and_even/1 function by replacing the atom tbi in the anonymous functions bound to the variable F.