Functional and concurrent programming with Erlang - Part I
As I mentioned in the Introduction to this series, today’s post will be about Erlang and its basic data types. We’ll get introduced to Erlang’s syntax and we’ll take a look at how functional programming concepts like single assignment have been realized.
Let’s start with a code snippet to compensate the lack of code in the introductory post. This is the famous hello world program in Erlang:
Since Erlang isn’t object-oriented like Java, Scala, Ruby or many other languages we will fail on our quest to find the class keyword in this snippet of code.
In Erlang, code is organized in modules. Modules are collections of functions which are saved in one file under one name (Erlang code is saved in files with the extension ‘.erl’). Actually all functions must be defined in a module and a module must have the same name as the file that contains the definiton of this module.
How to execute this code:
- Open a shell / command prompt
- Navigate to the directory where you keep your ‘helloworld.erl’ file
- Open the Erlang-Shell by typing ‘erl’
- c(modulename). compiles a module. Don’t forget the fullstop!
- You can call a module’s function(s) via the notation ‘module:function(parameter1, parameter2, …, parameterN).’
That was easy. But we can’t fully understand everything that’s on the screen, yet. So let’s figure out what’s going on here.
An Erlang module can contain two different things:
- and attributes
Attributes describe the module. The syntax for attributes is:
In our examples we used two attributes so far: module and export.
The module-attribute is the only one we have to put in our module. It tells the compiler our module’s name.
The export-attribute tells the compiler which functions of the module are accessible from outside of the module’s context. The syntax here is:
-export([function1/arity1, function2/arity2, …, functionN/arityN]).
Arity is just a fancy word for “number of parameters of this function”. Writing down the arity of a function in the export attribute is important because it’s possible to declare multiple functions with the same name as long as they have different arities.
Functions are functions as we are used to them from other languages. The function syntax is:
functionName (parameter1, parameter2, … parameterN) -> body
The body can either be a single expression or a sequence of expressions. Here’s an example for that:
As you can see we don’t use a return keyword. Still our functions do return the values one would expect them to according to their name.
The reason for that is, that in Erlang, a function returns the value of its body. In case of a body that contains only of one expression that’s pretty simple: A + B evaluates to the sum of A and B and therefore the function add returns the sum of A and B.
In case of a body that consists of a sequence of expressions the value of the last expression in that sequence gets returned.
When we look at the output of our hello world program, we can now explain where the ‘ok’ comes from that gets printed on the screen after “Hello, world!”: it must be the return-value of the fwrite() function since the call of this function is the first and - more importantly - the last statement of our hello() function.
The pieces that make up Erlang
Erlang is a relatively small language and doesn’t include a huge lot of built-in types. We’ll take a look at the most important ones. I’ll leave out a few to keep this semi-short so we can carry on and actually program something in the next post. So let’s get started:
If you ever programmed in any programming language there’s nothing too spectacular to see here:
If you want to work with numbers which aren’t in base 10 you can use the following notation:
For example: 2#101101 or 16#AB.
Erlang-Variables begin with capital letters or with an underscore. Variables beginning with an underscore are, by convention, reserved for values you want to save but don’t want to use later.
Erlang variables aren’t as variable as their name suggests. In fact Erlang implements the concept of single assignment which we looked at in the last post. Let’s write a simple function so we can quickly test that.
As you can see just trying to assign a new value to X isn’t possible.
When we’re talking about variables in Erlang it is VERY important to also talk about the ‘=’ operator. While most people will say “Well that’s a piece of cake: It assigns values to variables!”, we will have to stop and say:
The ‘=’ - Operator compares values and gets angry when they’re different (Like in the example we just looked at). If they are the same, it returns their value. If the left hand term is an unbound variable it first binds the right side value to the unbound variable and then compares them as usual.
This behavior is the foundation of something called pattern matching. It is a usual concept among functional programming languages and Erlang does it in a very flexible way. We’ll come back to it later.
A special case is the variable that consists of only an underscore ‘_’. It won’t store any value no matter how hard you try to assign a value to it. This seems pretty useless at first but will be very useful when we talk about List comprehension and pattern matching.
Atoms act like constants except that we don’t have to create them ourselves like Enumerables in Java. Every word that begins with a lowercase letter or that is written between two single quotes is an atom and except for the words that are reserved for Erlang (like ‘export’, ‘module’, ‘div’ or ‘rem’) all of them can be used as constants by the programmer. When an atom contains something else than alphanumeric signs or ‘@’ and ‘_’ you should write it between single quotes.
The value of an atom is the atom itself. So exampleatom has the value exampleatom and nothing more. Let’s check that in the Erlang console:
You should be careful with generating atoms automatically though because for every atom you use, Erlang creates an Entry in an atom-table. This table isn’t garbage collected! So creating too many atoms can result in an out of memory error.
The two boolean values ‘true’ and ‘false’ are atoms. It’s not like in C where 0 is false and everything else is true so don’t try to compare false and true with any numbers!
The comparison operators which test for equality look a little bit different than in other languages but there shouldn’t be anything too surprising here.
The other comparison-operators look like this:
< , >, >=, =<
Notice that the “less or equal” operator must be written with ‘=’ as the first symbol. This feels kind of wrong to me, so I felt like pointing that out.
This concludes my second post on this topic. Now that we talked about what functional programming is and how Erlang code looks like we laid a foundation that allows us to talk about the interesting stuff.
The next parts will be shorter and will discuss more specific topics and/or problems. This allows me to post more regularly and you don’t have to read through enormous walls of text.
The following part(s) will be about pattern matching and list comprehension and how they make solving certain problems easier.