Erlang in 5 minutes

Jan 10, 2020

X = erlang, Y = 5, io:format(“Learn ~s in ~s minutes”, [ X, Y ]).

Welcome to a 5-minute Erlang introduction!

First things first:

  • Erlang is a functional programming language
  • erl is the REPL shell
  • Ctrl + G and then q or q(). to exit the shell
  • c(file_name). to load the code from file

Now, to the language constructs:

  • every statement has to end with a dot (.) symbol
  • multiple statements are separated by comma (,) character
  • constants start with a Capital Letter
  • atoms (yes, like in Ruby) start with lowercase letter
  • atoms are allowed to contain spaces (sic!), but then they have to be quoted: 'atoms are awesome'
  • atoms can also have the at sign (@)
  • anonymous functions are defined as fun() -> return_statement end.
  • last statement before end must not end with comma
  • function signature is function_name/number_of_arguments: factorial/1, format/2
  • comments start with percent (%) symbol
  • lists are [ TheOnlyElement ] or [ Head | TailElements ], where TailElements is also a list
  • pattern matching just works [ Head1 | Head2 | Tails ] = [ 1, 2, 3, 4 ]
  • strings are just "strings"
  • tuples are quirky { elt1, elt2 }
  • maps are even weirder #{ key => value }
  • operators are almost fine:
    • comparison: < (less than), > (greater than), >= (greater than or equals to), =< (equals to or less than), == (equals to), /= (not equals to), =:= (adds type checking on tops, JS equivalent of ===)
    • assignment / pattern matching: =
    • math: +, -, *, /, div, rem (Pascal way)
    • typechecking: is_atom/1, is_function/1, is_number/1, is_boolean/1, is_pid/1, is_list/1, etc.
  • list comprehentions are similar to lists: [ N || N <- [ 1, 2, 3, 4, 5 ], N rem 2 == 0 ].
  • files are modules, defined with few statements:
    • -module(module_name).
    • -export([ list_of_function_signatures ]).
    • -import(module_name, [ list_of_functions ]).
  • calling module’s export be like module_name:function_name(arguments).

Quick recap:

%%% module comment
-module(erlang_example).

% exporting the functions from the module
-export([ factorial/1 ]).

% importing the functions from the other module
-import(my_other_module, [ new_factorial/1 ]).

% constants with pattern matching - will assign the value to non-defined constant on success
X = 5.

% redefinition is prohibited
X = 10. % exception

% functions can also be constants
PlusOne = fun(X) -> X + 1 end.

% or, multiline
PlusTwo = fun(X) ->
  X + 2

  end.

% the standard way
bad_factorial(N) ->
  N * factorial(N - 1).

%% function documentation
% functions can have *guargs*, which are basically pattern matching
% also, function overloading is split with semicolon (;)
factorial(N) when N =< 1 -> 1;

% last overload ends with dot (.)
factorial(N) -> N * factorial(N - 1).

% some return types
string_fn() -> "hello, world!".

list_fn() -> [ 1, "elements could be of different types too", -3.14, atom ].

function_function() ->
  fun(X) -> X mod 2 end.

dict_fn() -> #{ "key" => -3.14 }.

tuple_fn() -> { elt1, elt2, "elt 3" }.

%% note how overriden_function/1 has different definition than overriden_function/2
overriden_function(List) ->
  overriden_function(List, 0).

% the power of pattern matching!
overriden_function([ Head ], Acc) -> Acc + Head;

overriden_function([ Head1 | Head2 ], Acc) -> Acc + Head1 + Head2;

overriden_function([ Head | Tail ], Acc) ->
  overriden_function(Tail, Acc + Head);

overriden_function([], Acc) -> Acc.

complex_function(A, B) when A =< B -> A;
complex_function(A, B) when A > B -> B.

complex_function(A, B, C) ->
  X = complex_function(A, B),
  complex_function(X, C);

complex_function(A, B, C, D) ->
  X = complex_function(A, B),
  Y = complex_function(C, D),
  complex_function(X, Y).

fst({ First, _ }) -> First.

snd({ _, Second }) -> Second.

evens(List) -> [ X || X <- List, X rem 2 == 0 ].

keys(#{ Key => Value, _ => _ })

There also are few good resources on this: https://learnxinyminutes.com/docs/erlang/ and http://erlang.org/doc/apps/inets/http_client.html.