Index

getting started

installation
apt-get install erlang
hello world
-module(solution).
-export([main/0]).
main() -> io:fwrite("Hello World").

basics

boolean logic

true and true.
true or false.
false xor false.
not false.
short circuit operators
true orelse true.
false andalso true.
logical tests
5 =:= 5.    # is equal
2 =/= 3.    # is not equal
5 > 3.
2 < 3.
1 >= 1.
1 =< 1.

type checks

is_atom(Variable)
is_float(Variable)
is_integer(Variable)
is_boolean(Variable)
is_function(Variable)
is_list(Variable)
is_number(Variable)
is_tuple(Variable)

integers

integer from string
list_to_integer(Line)
integer to string
integer_to_list(Number)
calculations
a=1+2
modulo
R rem B
operators
https://www.tutorialspoint.com/erlang/erlang_operators.htm
absolute
abs(Number)

floats

format a float at 4 decimal precision
format_float(F) -> io_lib:format("~.4f", [F]).
math functions
http://erlang.org/doc/man/math.html

string

X="abc"
string concatenation
X="a" ++ "b"
X=concat("a", "b")
drop newlines
string:chomp(Line)
conversions
list_to_integer("5")
list_to_float("54.32")
strings documentation
http://erlang.org/doc/man/string.html

atom

conversions
atom_to_list(true)

tuple

Point = {2,3}.
get tuple size
size(Tuple)
tuple_size(Tuple)
get element
element(2, {a,b,c})
{ First, Second } = Tuple
convert to list
tuple_to_list(Tuple)

records

creating records
-record(point, {x=0,y=0,z=0}).
P1=#point{},
P2=#point{x=1},
P3=#point{x=1,y=1},
modifying an existing record
Modified = P3#point{z=1}
extracting a field
Modified#point.z
extracting fields using pattern matching
#point{x=X,y=Y,z=Z} = Modified
nested records
-record(details, {name="john doe"}).
-record(complex, {child=#details{}}).
C = #complex{child=#details{name="foo"}},
io:fwrite(C#complex.child#details.name).
records in guards
filter(#point{x=X,y=Y,z=Z}) when X > 0 -> io:fwrite(integer_to_list(Y) ++ "\n");
filter(_) -> noop.
P1=#point{x=0,y=0}.
P2=#point{x=1,y=1}.
P3=#point{x=1,y=2}.
lists:foreach(fun(E) -> filter(E) end, [P1,P2,P3]).
alternative implementation
filter(P = #point{}) when P#point.x > 0 -> io:fwrite(integer_to_list(P#point.y) ++ "\n");
filter(_) -> noop.
storing a record definition in a header file (.hrl)
-record(point, {x=0,y=0,z=0}).
loading a header file
-include("points.hrl").

documentation

http://erlang.org/doc/reference_manual/records.html

list

[97, 98, 99].
[1, {numbers,[1,2,3]}, 5.34, green].
adding elements
[1,2,3] ++ [4,5]
[ 1,2 | List ]
removing elements
[2,4,2] -- [2,4]
[1,2,3] -- [1,2] -- [3]
head
hd([1,2,3,4])
tail
tl([1,2,3,4])
pattern matching with the cons operator
List = [2,3,4]
NewList = [1|List]
[Head|Tail] = NewList
[NewHead|NewTail] = Tail
set comprehension (mapping)
[ 2*N || N <- [1,2,3,4] ]
set comprehension (filter)
[ X || X <- [1,2,3,4,5,6,7,8,9,10], X rem 2 =:= 0 ]
set comprehension (generators)
[ X+Y || X <- [1,2], Y <- [2,3] ]       %sum
[ {X,Y} || X <- [1,2,3], Y <- [1,2,3] ] %permutations
generator with filter
[ X || {X, fog} <- Weather ]
[ X || {a,X} = [ {a,1}, {b,2}, {a,4}, ignore ] ] % => [1,4]

key value pairs

using proplists
https://erldocs.com/maint/stdlib/proplists.html
using orddict
http://erldocs.com/maint/stdlib/orddict.html
using dicts
http://erldocs.com/maint/stdlib/dict.html
using general balanced trees
http://erldocs.com/maint/stdlib/gb_trees.html

built in functions

get element
lists:nth(3, [a, b, c, d, e])
get list size
length(List)
sequence: create list
lists:seq(1,4)
contains member
lists:member(X,Set)
reversing a list
lists:reverse(List)
for each
foreach(Fun, List) -> ok
mapping a list
Result = lists:map(fun (X) -> X+1 end, [5, 7, 3, 1])
filtering a list
Result = lists:filter(fun (X) -> X rem 2 =:= 0 end, [1,2,3,4,5,6])
fold / reduce
Reduce = fun(A,B) when A > B -> A; (_,B) -> B end,
Result = lists:foldl(Reduce, 0, [5, 7, 3, 1])

lists documentation

http://erlang.org/doc/man/lists.html

control flow

If statements

if_else(N) ->
    if N =:= 2 -> might_succeed;
       true -> always_does
    end
storing the result of an if pattern
Result = 
	if 
		X == a -> "one";
	    X == b -> "two";
	    true -> "other"
	end
if with and / or
if 
		X =:= 3; X =:= 5 -> threeorfive;
		X > 3; X < 7 -> betweenthreeandseven
	end

case statements

basic example
case lists:member(X,Set) of
	true  -> Set;
	false -> [X|Set]
end.
more complicated example
case Temperature of
	{celsius, N} when N >= 20, N =< 45 -> 'favorable';
	{kelvin, N} when N >= 293, N =< 318 -> 'scientifically favorable';
	{fahrenheit, N} when N >= 68, N =< 113 -> 'favorable in the US';
	_ -> 'avoid beach'
end.
block expressions
begin
	[expr]+
end

functions

noop function
simple() -> ok.
simple function with pattern matching
head([H|_]) -> H.
function clauses
factorial(0) -> 1;
factorial(N) when N>0 -> N * fact(N-1).
pattern matching with guard
old_enough(X) when X >= 16 -> true;
old_enough(_) -> false.
multiple guards
guard_and(X) when X >= 10, X =< 20 -> true;
guard_and(_) ->	false.

guard_or(X) when X < 10; X > 20 -> false;
guard_or(_) -> true.
passing a same module function as a reference
increment(E) -> E + 1.
Mapped = lists:map(fun increment/1, [1,2,3])
passing an exported function as a reference
Mapped = lists:map(fun solution:increment/1, [1,2,3])
anonymous function
Mapped = lists:map(fun(X) -> X + 1 end, [1,2,3])
function as variable
Increment = fun(X) -> X + 1 end,
Mapped = lists:map(Increment, [1,2,3])
returning a function from a function
Return = fun() -> fun() -> io:fwrite("returned function") end end,
Again = Return(),
Again().
Parameterizing a function before calling it
Increment = fun(X) -> Y = X + 1, 
					fun() -> io:fwrite("incremented:" ++ integer_to_list(Y)) end 
			end,
Val = Increment(3),
Val().
inline function with recursion
Factorial = fun Calc(N) -> 
					if 
						N =:= 1 -> 1;
						true -> N * Calc(N-1)
					end
				end,

documentation

http://erlang.org/doc/reference_manual/functions.html

IO

print a string
io:fwrite("hello world\n")
io:format("Hello, world!~n")
print a number
io:fwrite(integer_to_list(5))
io:format("~b ~b\n", [2,3])
write a list of strings
io:write(First),
io:fwrite(List)
io:format("~w~n", [List])
read line from standard input
io:get_line("")
navigating the filesystem
cd("/tmp").
systemcompiling a module
c(module).

documentation

http://erlang.org/doc/man/io.html

exception handling

throw an error
error("boe"),
exit process
exit(0),
throw exception
throw(catchme)
try catch
try error(blabla) 
	catch
		error:blabla -> io:fwrite("blabla error.\n")
end,
catching various types of faults
try F() 
	catch
		throw:type -> "for use with throw";
		error:type -> "for use with error";
		exit:type -> "for use with exit";
		_ -> "unknown thrown exception"
		_:_ -> "anything else."
end.
try catch with return value
try error(blabla) of
		_ -> ok
	catch
		error:blabla -> nok
end,
finally
try F() of
	_ -> "completed ok"
after
	io:fwrite("finally.\n")
end
get stack trace
Trace = 
	try 
		throw(dummy)
	catch
		throw:dummy:Stacktrace -> Stacktrace
	end,
erlang:display(Trace)
catch both succesful execution and unsuccesful execution
catch F()

documentation

http://erlang.org/doc/reference_manual/errors.html

macros

-define(sub(X,Y), X-Y).
?sub(10,8)

behaviors

defining a behavior
-module(my_behaviour).
-export([behaviour_info/1]).
behaviour_info(callbacks) -> [{init,1}, {other, 3}];
behaviour_info(_) -> undefined.
implementing a behavior
-behaviour(gen_server).

documentation

https://erlang.org/doc/getting_started/users_guide.html
https://erlang.org/doc/reference_manual/users_guide.html
https://erlang.org/doc/search/