Erlang Programming/guards

Guard structures
Legal guards in Erlang are boolean functions placed after the key word, "when" and before the arrow, "->". Guards may appear as part of a function definition or in "receive", 'if', "case", and "try/catch" expressions.

We can use a guard in a function definition Example program: guardian.erl

-module(guardian). -compile(export_all). the_answer_is(N) when N =:= 42 -> true; the_answer_is(N) -> false. % ============================================= >% % % Example output: % % c(guardian). % ok % % guardian:the_answer_is(42). % true % % guardian:the_answer_is(21). % false

and Fun definition

F = fun (N) when N =:= 42 -> true; (N) -> false end.

receive expression

receive {answer, N} when N =:= 42 -> true; {answer, N} -> false end.

if expression

if    N =:= 42 -> true; true -> false end.

case expression

case L of   {answer, N} when N =:= 42 -> true; _ -> false end.

and try/catch

try find(L) of    {answer, N} when N =:= 42 -> true; _ -> false catch {notanumber, R} when is_list(R) -> alist; {notanumber, R} when is_float(R) -> afloat _ -> noidea end.

You will notice that in these examples it would be clearer (in real code) to remove the guard and modify the pattern matching instead.

Literate programming note: Anonymous match variables that start with an underscore like "_" are not generally recommended. Rather, it is nice to use some descriptive variable name like "_AnyNode". On the other hand, for tutorial code like this, a descriptive variable is more distracting than helpful.

case L of   {node, N} when N =:= 42 -> true; _AnyNode -> false end.

Multiple guards
It is possible to use multiple guards within the same function definition or expression. When using multiple guards, a semicolon, ";", signifies a boolean "OR", while a comma, ",", signifies boolean "AND".

the_answer_is(N) when N == 42, is_integer(N) -> true; geq_1_or_leq_2(N) when N >= 1; N =< 2 -> true;

Guard functions
There are several built-in-functions (BIFs) which may be used in a guard. Basically we are limited to checking the type with, is_type(A) and the length of some types with, type_size or length(L) for a list length.

is_alive/0 is_boolean/1 is_builtin/3 is_constant/1 is_float/1 is_function/2     is_function(Z, Arity) is_function/1 is_integer/1 is_list/1 is_number/1 is_pid/1 is_port/1 is_record/3 is_record/2 is_reference/1 is_tuple/1 tuple_size/1 is_binary/1 is_bitstring/1 bit_size/1 byte_size/1 length(Z) > N map_size(M)

A > B A < B A == B A =< B A >= B A /= B A =:= B    exactly equal A =/= B    exactly not equal

Note: all erlang data types have a natural sort order.

atom < reference < port < pid < tuple < list ...