We are a software consultancy based in Berlin, Germany. We deliver
high quality web apps in short timespans.

Upstream Agile GmbH

Programming Erlang: Functional Programming

July 24, 2007 by alex

I started reading the book Programming Erlang and while I read I blog along what I find most interesting/important. In the end, this will hopefully be some kind of erlang tutorial, for your pleasure and my reference :) Here’s the first post and now comes the second:

Yesterday I started reading the next chapter called “Sequential Programming”. It actually is about functional programming: functions, anonymous functions, higher order functions, predicates, pattern matching for calling functions a.s.o. - I had to read most of it twice to actually understand it and haven’t even finished the chapter yet. Anyway, let’s start. By the way I started creating an Erlang Cheat Sheet with all the syntax on it. Being used to the very clear Ruby syntax, things started to get a bit confusing in this chapter.

functions

Note: You can not enter function definitions in the erlang shell erl. see the modules section below to learn how to run this code.

A function in erlang is a function as in any (?) language. It receives parameters and returns a value (well, there’s more, read on). The definition looks like this:

area({rectangle, Width, Height}) -> Width * Height;

This defines the function area which takes a tuple containing the atom rectangle (to identify the type of shape) and its with and height. It of course returns the area of the rectangle by multiplying width and height.

parameter matching

We can now define the same function again with different parameters, e.g. like this:

area({circle, Radius}) -> Radius * Radius * 3.14 .

As you might have guessed already, this now computes the area of a circle. The cool thing is, that when you now call area, erlang works out which of the function to call, depending on the given parameters. If you pass a tuple with the atom rectangle as its first element and two values, the first definition matches ({rectangle, Width, Height}). With circle and one value, the second one matches.
Note: the order of the function definitions id important, erlang starts with the first and goes down the list until it finds a match. But this is only important if you call a function where multiple definitions will match your parameters.

List recursions

one thing you can do with this pattern matching is processing lists recursively. for example, you could define a function that takes a list of numbers and returns the negated values. you do this by defining two functions: one takes a list with at least one element in it. this function does the computation with the head (first element) and then calls itself recursively with the tail (rest) of the list. the second definition expects an empty list and simply denotes the end of the recursion. take a look:

negate([Head|Tail]) -> [Head * -1] ++ negate(Tail);
negate([]) -> [].
negate([1,2,3]). % [-1, -2, -3]

The first definition computes the negated value of the head. It then puts the result in a list (the angle brackets around the Head * -1) and concatenates the result of the computation of the tails - which is again a list of values.

Modules

Modules are as usual collections of functions. A module definition starts with -module(my_module).. after that you have to export all the functions you want to use from outside of the module using -export([my_function/1]). where the /1 denotes the arity of the function (the number of aruments).

-module(my_module).
-export([hello_world/0]).
hello_world() -> "hello world".

If you want to run any of the functions above, you have to put them into a module and save it as a .erl file. You can then compile and use the module from the shell:

c(my_module).
my_module:hello_world() % "hello world"

So that was the easy part of this chapter (chapter 3 in the book) but enough already for this post. Stay tuned for more.