Getting started with Erlang

Eshell V7.0  (abort with ^G)
1> ok.
ok
2>

Variables Types

This is the first thing we will deal with. Following are a few variable types that you will need as of now(in erlang comments begin with %),

Eshell V7.0  (abort with ^G)
1> "Hello World". % this is how you write a string
"Hello World"
2> 42. % this is how you write a number
42
3> 4.2. % this how to write a decimal
4.2
4> ["Hello", 4.2]. % this how to write a list
["hello",4.2]
5> {"Hello", 4.2}. % this how to write a tuple

Variables

Now that you have knowledge about variables types you would want to store them somewhere and do stuff to them ! Following is how you declare a variable

6> SomeVar = "Hello World".
"Hello World"
  • variable name in Erlang ALWAYS starts with a capital letter ! (don’t fight this … just accept it and move ahead)
7> NewVar = "Hello World".
"Hello World"
8> NewVar = "Testing".
** exception error: no match of right hand side value "Testing"
9> Var1.
* 1: variable 'Var1' is unbound
10> Var1 = "Hello World".
"Hello World"
11> Var1 = "New stuff".
** exception error: no match of right hand side value "New stuff"
12> Var1 = "Hello World".
"Hello World"
  • At 9 we didn’t have the variable assigned so it said unbound, that is what it always says if the variable has not been assigned any value.
  • At 10 we assigned a value and everything is fine.
  • At 11 we try to reassign and it throws an error.
  • At 12 we assigned “Hello World” value again and it's happy. What ! I thought that variables could not be reassigned ?? The reason the last statement worked because the value stored in Var1 matched to “Hello World” so no reassignment has taken place but the match is successful !

Atoms

Here I will introduce another variable type called “atom”. I know I said we will start with some common ground but atoms are really at heart of what we are going to do next. Following is how to write an atom.

13> helloworld.
helloworld
14> 'Hello World'.
'Hello World'

Module

Now that we are through with writing variables, let’s learn how to create a module and write your first Erlang program. Create a file named “hello_world.erl” and add the following to it,

-module(hello_world).-export([hello_world/0]).hello_world() -> "Hello World".
  • The first line declares the module name and the module name should be same as that of the filename. Since our file was named “hello_world.erl” we used “-module(hello_world).” . Notice that module name is atom (first usage of atoms !)
  • The second line allows user to define a list of function names that you want to expose to the universe. Notice the list element hello_world/0 , here the last part i.e. “/0” represent the arity (the number of argument parameters the function takes as input) of the function. An example usage of export is follows (notice the function names are also atoms !),
-export([first_function/1, second_function/2]).
  • Here we expose 2 functions i.e. first_function and second_function. The first_function has an arity of 1 and second_function has an arity of 2.
  • In the third line of our module we write our first function i.e.
hello_world() -> "Hello World".% function_name(Arg1, Arg2, ...) -> do_something.
  • notice the odd “->” , you have to use it after you complete writing the function head. Just like in python you write,
def fuction_name(args):
return "ok"
funtion_name(args) ->
ok.
% or
funtion_name(args) -> ok.
  • The last statement in an Erlang functions is automatically returned. The above function returns the atom “ok”.
  • Another thing to notice is how we have used “.” Recall that I said whenever we complete a sentence you have to use “.” So I wrote the above module i.e. hello_world.erl as set of sentences such that each one has a “.” at the end of it. To make it explicit whenever you end a function use “.”
add(A, B) -> A + B.multiply(A, B) -> A*B.divide(A, B) -> A/B.
-module(hello_world).-export([hello_world/0, add/2, multiply/2, divide/2]).hello_world() -> "Hello World".add(A, B) -> A + B.multiply(A, B) -> A*B.divide(A, B) -> A/B.
15> c(hello_world).
ok
16> hello_world:hello_world().
"Hello World"
17> hello_world:add(1,2).
3
18> hello_world:multiply(1,2).
2
19> hello_world:divide(1,2).
0.5
area_triangle(A, B, C) ->
S = (A + B + C)/2,
math:sqrt(S*(S-A)*(S-B)*(S-C)).
  • The first line is the function head, function name is area_triangle which takes the 3 variables i.e. the sides of the triangle as argument.
  • The second line does some calculation but the thing to notice here is the “,” . So when you write a multi line function we need to tell the compiler where a segment ends. Also when you write the last segment for your function you end it with “.” because this completes your and recall that when we complete a sentence we end it with “.” So you can view the above function like a sentence as below where each of the segment end with a “,” and the last segment end with “.” because it marks the end of sentence.
area_triangle(A, B, C) -> S = (A + B + C)/2, math:sqrt(S*(S-A)*(S-B)*(S-C)).
  • In the last line we just use the sqrt function from the in-built math module to calculate the square root.

Pattern Matching

The simplest way to put pattern matching is that things that look similar will match and things that don't will not … huhh obvious, right ! for eg.

Var1 = "I love Erlang".
Var2 = "I love Erlang".
Var1 = Var2. % output will be: "I love Erlang"
1> Var1 = "I love Erlang".
"I love Erlang"
2> Var1 = "something else".
** exception error: no match of right hand side value "something else"
1> List = ["I", "love", "Erlang"].
["I","love","Erlang"]
2> [A, B, C] = List.
["I","love","Erlang"]
3> A.
"I"
4> B.
"love"
5> C.
"Erlang"
6> [A, B, C] = ["I", "hate", "Erlang"].
** exception error: no match of right hand side value ["I","hate","Erlang"]
  • In the first line we just assign a list to the variable “List”.
  • Next we try to pattern match “List” with [A, B, C] which is a list of unbound variables. Recall, I told you that Erlang will assign values to variables if they unbound and match them if they are bound. Since all “A”, “B” and “C” are unbound and the list sizes are same on both sides i.e. 3 the match ends up assigning values to “A”, “B” and “C”.
  • In the sixth line we try to match again but since variables already have value assigned the match fails. In short you can't hate Erlang !
1> List = ["I", "love", "Erlang", "even", "more"].
["I","love","Erlang","even","more"]
2> [A, B | C] = List.
["I","love","Erlang","even","more"]
3> A.
"I"
4> B.
"love"
5> C.
["Erlang","even","more"]
6>
1> List = ["I", "love", "Erlang"].
["I","love","Erlang"]
2> [A, B, C | D] = List.
["I","love","Erlang"]
3> D.
[]
4> [E, F, G, H | I] = List.
** exception error: no match of right hand side value ["I","love","Erlang"]

Functions and Pattern matching

You can pattern match in functions too ! But how is that helpful you might ask. Ok let see some examples,

is_zero(0) -> true;
is_zero(N) -> false.
  • Firstly, these are not two functions it is a single function which two clauses. The first clause ends at “;” after which the second clause begins. In general clauses in Erlang end with “;” . I will give a few other places where clauses come into picture later.
  • How does pattern match work here ? Suppose you use the above function as follows,
is_zero(7).   % false
array_sum([], Sum) ->
Sum;
array_sum([Element | Rest ], Sum) ->
array_sum(Rest, Sum + Element).
array_sum([1,2,3,4,5], 0).  % 15
  • When you execute this function, recall it will try to pattern match the first clause but it will fail because the first argument in the function is an empty list i.e. “[]” but we passed in a list which is not empty so it will fail.
  • Then it tries to match the second clause which will match because all the arguments are unbound and they get bound to the values we pass in. But for the first argument the pattern match will also extract an array element and bind it to “Element” and rest of the array will be stored in “Rest”.
  • We then call array_sum again but this time we pass “Rest” instead of the whole array and add the variable “Element” extracted from the list to “Sum”. So our next call will look like this
array_sum([2,3,4,5], 1)array_sum([3,4,5], 3)   % next call
  • This way each element will get added to “Sum” and finally we will have “[]” i.e. empty list. Now the empty list match the first clause and at this point we know we have no elements left to add. So we returns the variable “Sum”.
%% case statements
is_zero(N) ->
case SomeVariable of
0 -> true;
N -> false
end.
%% if statement
is_zero(N) ->
if
N =/= 0 -> false;
true -> true
end.

--

--

https://github.com/kansi

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store