Tag Archives: erlang

Introduction to Erlang part 1

Erlang is a functional programming language. If you have ever worked with imperative languages, statements such as i++ may be normal to you; in functional programming they are not allowed. In fact, changing the value of any variable is strictly forbidden.

We will start with installing Erlang.

Installation:

sudo apt-get install erlang

In Erlang, you can test most of your stuff in an emulator; it will run your scripts
and  it will also let you edit stuff live. To start,  open a terminal and then type $ erl. If you’ve set up everything fine, you should see text like this:

Shell

Erlang R13B01 (erts-5.7.2) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.2  (abort with ^G)

Shell commands:

User switch command
--> h
c [nn]            - connect to job
i [nn]            - interrupt job
k [nn]            - kill job
j                 - list all jobs
s [shell]         - start local shell
r [node [shell]]  - start remote shell
q  - quit erlang
? | h             - this message
-->

If you type in i then c, Erlang should stop the currently running code and bring you back to a responsive shell. J will give you a list of processes running (a star after a number indicates this is the job you are currently running), which you can then interrupt with i followed by the number. If you use k , you will kill the shell as it is instead of just interrupting it. Press s to start a new one.

Eshell V5.7.2  (abort with ^G)
1> "OH NO THIS SHELL IS UNRESPONSIVE!!! *hits ctrl+G*"
User switch command
--> k
--> c
Unknown job
--> s
--> j
2* {shell,start,[]}
--> c 2
Eshell V5.7.2  (abort with ^G)
1> "YESS!"

Now we will go through some basics

In the Erlang shell, expressions have to be terminated with a period followed by whitespace(line break, a space etc.), otherwise they won’t be executed. You can separate expressions with commas, but only the result of the last one will be shown (the others are still executed). This is certainly unusual syntax for most people and it comes from the days Erlang was implemented directly in Prolog, a logic programming language.

Here is example,

1>2 + 15. 
17
2> 49 * 100.
4900
3> 1892 - 1472.
420
4> 5 / 2.
2.5
5> 5 div 2.
2
6> 5 rem 2.
1

 

Erlang doesn’t care if you enter floating point numbers or integers: both types are supported when dealing with arithmetic.Integers and floating values are pretty much the only types of data Erlang’s mathematical operators will handle transparently for you.

Note that we can use several operators in a single expression, and mathematical operations obey the normal precedence rules.

7> (50 * 100) - 4999.
1
8> -(50 * 100 - 4999).
-1
9> -50 * (100 - 4999).
244950

If you want to express integers in other bases than base 10, just enter the number as Base#Value (given Base is in the range 2..36):

10> 2#101010.
42
11> 8#0677.
447
12> 16#AE.
174

 

Invariable Variables

Doing arithmetic is alright, but you won’t go far without being able to store results somewhere. For that, we’ll use variables. If you have read the intro to this book, you’ll know that variables can’t be variable in functional programming. The basic behavior of variables can be demonstrated with these 7 expressions (note that variables begin with an uppercase letter):

#Erlang Shell
1> One.
* 1: variable 'One' is unbound
2> One = 1.
1
3> Un = Uno = One = 1.
1
4> Two = One + One.
2
5> Two = 2.        
2
6> Two = Two + 1.
** exception error: no match of right hand side value 3
7> two = 2.
** exception error: no match of right hand side value 2

The first thing these commands tell us is that you can assign a value to a variable exactly once; then you can ‘pretend’ to assign a value to a variable if it’s the same value it already has. If it’s different, Erlang will complain. It’s a correct observation, but the explanation is a bit more complex and depends on the = operator. The = operator (not the variables) has the role of comparing values and complaining if they’re different. If they’re the same, it returns the value:

8> 47 = 45 + 2.
47
9> 47 = 45 + 3.
** exception error: no match of right hand side value 48

IMPORTANT POINTS TO NOTE:

1) This behavior of the = operator is the basis of something called 'Pattern matching'
2) Variable names must begin with a capital letter.
3) Technically, variables can start with an underscore ('_') too, but by convention their use is restricted to values you do not care about, yet you felt it was necessary to document what it contains.
4) '_' Unlike any other kind of variable, it won't ever store any value.

Data Types:

1) Terms
2) Numbers
3) Atom
4) Bit Strings and Binaries
5) Reference
6) Fun
7) Port Identifier
8) Pid
9) Tuple
10) Map
11) List
12) String
13) Record
14) Boolean
15) Type Conversions

1) Terms: A piece of data of any data type is called a term.

2) Number: There are two types of numeric literals, integers and floats. Besides the conventional notation, there are two Erlang-specific notations:

$char ASCII value or unicode code-point of the character char.

base#value Integer with the base base, that must be an integer in the range 2..36. In Erlang 5.2/OTP R9B and earlier versions, the allowed range is 2..16.

Examples:

1> 42.
42
2> $A.
65
3> $\n.
10
4> 2#101.
5
5> 16#1f.
31
6> 2.3.
2.3
7> 2.3e3.
2.3e3
8> 2.3e-3.
0.0023

3) Atom

Examples:

hello
phone_number
'Monday'
'phone number'

4) Bit Strings and Binaries

A bit string is used to store an area of untyped memory. Bit strings are expressed using the bit syntax. Bit strings that consist of a number of bits that are evenly divisible by eight, are called binaries.

Examples:

1> <<10,20>>.
<<10,20>>
2> <<"ABC">>.
<<"ABC">>
1> <<1:1,0:1>>.
<<2:2>>

5) Reference

A reference is a term that is unique in an Erlang runtime system, created by calling make_ref/0.

6) Fun

A fun is a functional object. Funs make it possible to create an anonymous function and pass the function itself — not its name — as argument to other functions.

Example:

1> Fun1 = fun (X) -> X+1 end.
#Fun<erl_eval.6.39074546>
2> Fun1(2).
3

7) Port Identifier

A port identifier identifies an Erlang port. open_port/2, which is used to create ports, returns a value of this data type.

8) Pid

A process identifier, pid, identifies a process. The following BIFs, which are used to create processes, return values of this data type:

spawn/1,2,3,4 spawn_link/1,2,3,4 spawn_opt/4

Example:

1> spawn(m, f, []).
<0.51.0>

9) Tuple

A tuple is a compound data type with a fixed number of terms: Each term Term in the tuple is called an element. The number of elements is said to be the size of the tuple. There exists a number of BIFs to manipulate tuples.

Examples:

1> P = {adam,24,{july,29}}.
{adam,24,{july,29}}
2> element(1,P).
adam
3> element(3,P).
{july,29}
4> P2 = setelement(2,P,25).
{adam,25,{july,29}}
5> tuple_size(P).
3
6> tuple_size({}).
0

10) Map

A map is a compound data type with a variable number of key-value associations: ex: {Key1=>Value1,…,KeyN=>ValueN}

Each key-value association in the map is called an association pair. The key and value parts of the pair are called elements. The number of association pairs is said to be the size of the map.

Examples:

1> M1 = #{name=>adam,age=>24,date=>{july,29}}.
#{age => 24,date => {july,29},name => adam}
2> maps:get(name,M1).
adam
3> maps:get(date,M1).
{july,29}
4> M2 = maps:update(age,25,M1).
#{age => 25,date => {july,29},name => adam}
5> map_size(M).
3
6> map_size(#{}).
0

11) List

A list is a compound data type with a variable number of terms. [Term1,…,TermN] Each term Term in the list is called an element. The number of elements is said to be the length of the list.

Formally, a list is either the empty list [] or consists of a head (first element) and a tail (remainder of the list). The tail is also a list. The latter can be expressed as [H|T]. The notation [Term1,…,TermN] above is equivalent with the list [Term1|[…|[TermN|[]]]].

[] is a list, thus 
[c|[]] is a list, thus 
[b|[c|[]]] is a list, thus 
[a|[b|[c|[]]]] is a list, or in short [a,b,c]

A list where the tail is a list is sometimes called a proper list. It is allowed to have a list where the tail is not a list, for example, [a|b]. However, this type of list is of little practical use.

Examples:

1> L1 = [a,2,{c,4}].
[a,2,{c,4}]
2> [H|T] = L1.
[a,2,{c,4}]
3> H.
a
4> T.
[2,{c,4}]
5> L2 = [d|T].
[d,2,{c,4}]
6> length(L1).
3
7> length([]).
0

13) Record A record is a data structure for storing a fixed number of elements. It has named fields and is similar to a struct in C. However, a record is not a true data type. Instead, record expressions are translated to tuple expressions during compilation. Therefore, record expressions are not understood by the shell unless special actions are taken.

-module(person).
-export([new/2]).

-record(person, {name, age}).

new(Name, Age) ->
#person{name=Name, age=Age}.

1> person:new(ernie, 44).
{person,ernie,44}

14) Boolean

There is no Boolean data type in Erlang. Instead the atoms true and false are used to denote Boolean values.

Examples:

1> 2 =< 3.
true
2> true or false.
true

15) Type converstions

 1> atom_to_list(hello).
"hello"
2> list_to_atom("hello").
hello
3> binary_to_list(<<"hello">>).
"hello"
4> binary_to_list(<<104,101,108,108,111>>).
"hello"
5> list_to_binary("hello").
<<104,101,108,108,111>>
6> float_to_list(7.0).
"7.00000000000000000000e+00"
7> list_to_float("7.000e+00").
7.0
8> integer_to_list(77).
"77"
9> list_to_integer("77").
77
10> tuple_to_list({a,b,c}).
[a,b,c]
11> list_to_tuple([a,b,c]).
{a,b,c}
12> term_to_binary({a,b,c}).
<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>
13> binary_to_term(<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>).
{a,b,c}
14> binary_to_integer(<<"77">>).
77
15> integer_to_binary(77).
<<"77">>
16> float_to_binary(7.0).
<<"7.00000000000000000000e+00">>
17> binary_to_float(<<"7.000e+00>>").
7.0