I recently had a chance to learn Erlang. In the beginning, it was quite hard to find a good book or tutorial that gave a clear idea of the language and the best practices. Hoping this blog can help someone who wants to get started.
As I began, it started to strike me that modern languages like Go, Ruby, Javascript have parts which have some similarity with Erlang. The parts include concurrency aspects w.r.t. passing messages using channels in Golang, the way functions return results of last executed expression in Ruby and first class functions in Golang/Javascript.
Erlang’s history revolves around telecom industry. It has been known for concurrency using light-weight processes, fault-tolerance, hot loading of code in production environments etc. The Open Telecom Platform (OTP) is another key aspect of Erlang which provides the framework for distributed computing and all other aspects mentioned above.
Some key points to keep in mind,
- Values are immutable
- Assignment operator (=) and functions work based on pattern matching
- No iterative statements like for, while, do..while.. etc. recursive functions serve the purpose
- Lists, Tuples (records – a hack using tuples) are very important data structures
- If, Case.. Of.. are the conditional blocks
- Guards are additional pattern matching clauses used with functions and Case.. Of..
- Every expression should return a value and last expression in a function automatically returns the result
- Functions are first class citizens
- Usage of punctuations ‘; , .’ etc. (one can relate this to indentation requirements in python)
Lets gets started with some code samples,
% Execute this from erlang shell. erl is the command
> N = 10.
10
%% The above statement compares N with 10 and binds N with 10 if its unbound. If its already bound with some other value, exception is thrown.%% Tuple
> Point = {5, 6}
{5,6}%% List
> L = [2, 5, 6, 7].
[2, 5, 6, 7]%% Extracting Head and Tail from List is key for List processing/transformations
> [H|T] = [2, 5, 6, 7].
>H.
2
>T.
[5, 6, 7]%% List comprehensions
> Even = [E || E <- L, E rem 2 =:= 0].
[2,6]
Lets take a look at the simple functions,
helloworld () -> hello_world.
The simple function will return hello_world, a constant string – atom. Lets have a look at a recursive function,
%% Factorial of N
factorial (N) when N =:= 0 -> 1;
factorial (N) -> N * factorial(N-1).%% Tail recursion
tail_factorial (N) -> tail_factorial(N, 1).
tail_factorial (0, Acc) -> Acc;
tail_factorial (N, Acc) -> tail_factorial (N-1, Acc * N).
The factorial functions demonstrate how Erlang does pattern matching on function parameters, usage of Guard (‘when’ clause), punctuations. We could have also written the statement as ‘factorial(0) -> 1;’ .
The second version tail_factorial demonstrates the optimized version using tail recursion to simulate the iterative method. In this method Erlang would remove the previous stack frames using Last Call Optimization (LCO). It is important to understand both techniques as recursion is used quite extensively.
Erlang has the following data types – atom, number, boolean (based on atom), strings and binary data. atom’s occupy more space and its better to using binary data type for strings of larger sizes.
Other builtin data structures are queues, ordsets, sets, gb_trees . Error, Throw, Exit, Try.. Of .. Catch statements provide the exception handling capabilities.
The most interesting part of the language is about spawning light weight processes and passing messages between them,
– module (dolphin-server).%% API– export ([dolphin_handler/0]).dolphin_handler() ->receivedo_a_flip ->io:format (“How about no ? ~n”);fish ->
io:format (“So long and thanks for the fish! ~n”);_ ->io:format (“we’re smarter than you humans 😉 ~n”);end,dolphin_handler().%% From shell, compile dolphin-server module>c(‘dolphin-server’).
%% Spawns a new process
> Dolphin = spawn (‘dolphin-server’, dolphin_handler, []).<0.124.0> %% process id of the newly spawned process
%% Now start passing messages!!
> Dolphin ! fish.
So long and thanks for the fish!>Dolphin ! “blah blah”we’re smarter than you humans 😉
Open Telecom Platform (OTP)
- gen_server – for implementing server side piece in client/server
- supervisor – for implementing a supervisor in a supervisor tree. It takes care of the details regarding restarting of processes, fault-tolerance etc.
- gen_event – for implementing event handling functionality
- gen_statem – for implementing state machines
https://learnyousomeerlang.com/contents is one of the best online books for understanding how to use Erlang, best practices while building an application which is production ready. Its good to take pauses and move with book as its quite exhaustive, but wonderfully written 🙂