This way, if there is no an answer after 3 seconds, the function will return timeout.

Conclusion: don’t add a receive block on a non spawned function unless you know what you are doing.

Flush my mailbox

Add some messages to your mailbox:

44> self() ! self() ! self() ! new_message

Then, flush and print them using your own version of flush:

flush() ->
receive
Any -> io:format("~p~n", [Any]), flush()
after 0 -> ok % if you comment this line,
% it will be waiting for more messages in the mailbox
end.

This function works as follows.

1. Given that a receive block is involved, flush will read its mailbox looking for a message that match the pattern Any (in this case, all the messages match).
2. Then, the message is printed, removed from the mailbox, and flush is started again.
3. When the mailbox is empty, the function will wait for 0 secs and return ok.

Guards: (orelse,andalso) vs. (;,)

According to lyshfgg, andalso and orelse are preferred to , and ; when exception handling is involved.

if and pattern matching

These two snippets are equivalent. Obviously, the latter is shorter and cleaner.

about pids and spawned process
The pid of a spawned process does not change after sending several messages. Also, if a function is spawned n times, then there will be n different pids. Consider the following snippet:

The idea is to keep the result of each operation using a temporary variable called accumulator (Acc). When the recursion process is finished (i.e. the base case is reached), the accumulator is returned. In the following example, the previous function will be implemented using message passing. To this end, we will follow the pattern described in the previous point (about pids and spawned process).

We start with a simple function which takes as parameters the pid of the shell (i.e. the pid that will receive the output of the factorial function) and the number which factorial will be computed.

start_sfactorial(From, N)

This function is almost the same as start_process, previously described. The goal of this function is to spawn the main process, in our case, to compute the factorial of a given number.

First, we spawn a function called sfactorial, which takes a single value as parameter: the pid that will receive the answer (From). Then, the spawned pid is printed (SpawnedPid). The next line is the most important one. In this line, the factorial process is started by sending an initial message with this format:

SpawnedPid ! {SpawnedPid, N, Acc}

where SpawnedPid represents the pid of the [spawned] factorial function (sfactorial), N is the number which factorial will be computed, and Acc is our accumulator. At the beginning, the accumulator is 1 (the same as tail_fact). Finally, SpawnedPid is returned, but this step can be omited or replaced by an ok atom.

In this case, we are asking for the factorial of an atom: number. That is, we can send anything to Pid, even if it is not a number. In order to avoid this, we can use guards. The next snippet contains a better implementation of our previous function, now using guards. Also, we added a new clause to output a comment when the received message did not matched any pattern.