Erlang is a concurrent programming language – this means that parallel activities (processes) can be programmed directly in Erlang and that the parallelism is provided by Erlang and not the host operating system.

In order to control a set of parallel activities Erlang has primitives for multi- processing: spawn starts a parallel computation (called a process); send sends a message to a process; and receive receives a message from a process.

spawn/3 starts execution of a parallel process and returns an identifier which may be used to send messages to and receive messages from the process.

The syntax Pid ! Msg is used to send a message. Pid is an expression or constant which must evaluate to a process identity. Msg is the message which is to be sent to Pid. For example:

Pid ! {a, 12}

means send the message {a, 12} to the process with identifier Pid (Pid is short for process identifier). All arguments are evaluated before sending the message, so:

foo(12) ! math3:area({square, 5})

means evaluate the function foo(12) (this must yield a valid process identifier) and evaluate math3:area({square, 5}) then send the result (i.e. 25) as a message to the process. The order of evaluation of the two sides of the send primitive is undefined.

The primitive receive is used to receive messages. receive has the following syntax:

receive
    Message1 ->
        ... ;
    Message2 ->
        ... ;
        ...
end

This means try to receive a message which is described by one of the patterns Message1,Message2,... The process which is evaluating this primitive is sus- pended until a message which matches one of the patterns Message1,Message2,... is received. If a match occurs the code after the -> is evaluated.

Any unbound variables occurring in the message reception patterns become bound if a message is received.

The return value of receive is the value of the sequence which is evaluated as a result of a receive option being matched.

While we can think of send as sending a message and receive as receiving a message, a more accurate description would be to say that send sends a message to the mailbox of a process and that receive tries to remove a message from the mailbox of the current process.

receive is selective, that is to say, it takes the first message which matches one of the message patterns from a queue of messages waiting for the attention of the receiving process. If none of the receive patterns matches then the process is suspended until the next message is received – unmatched messages are saved for later processing.

1.5.1. An echo process

As a simple example of a concurrent process we will create an echo process which echoes any message sent to it. Let us suppose that process A sends the message {A, Msg} to the echo process, so that the echo process sends a new message containing Msg back to process A. This is illustrated in Figure 1.1.

// TODO: FIGURE !!!

In Program 1.5 echo:start() creates a simple echo process which returns any message sent to it.

-module(echo).
-export([start/0, loop/0]).

start() ->
    spawn(echo, loop, []).

loop() ->
    receive
        {From, Message} ->
            From ! Message,
            loop()
    end.

spawn(echo, loop, []) causes the function represented by echo:loop() to be evaluated in parallel with the calling function. Thus evaluating:

...
Id = echo:start(),
Id ! {self(), hello}
...

causes a parallel process to be started and the message {self(), hello} to be sent to the process – self() is a BIF which returns the process identifier of the current process.