Photo by Christopher Gower on Unsplash

What to expect when you’re expecting: Playing with processes in Erlang

Mehrdad Esmaeilpour
Level Up Coding
Published in
3 min readMar 12, 2020

--

Erlang’s key organizational concept is the process, an independent component (built from functions) that sends and receives messages. Programs are deployed as sets of processes that communicate with each other. Erlang concurrency is based on processes. These are small, self-contained virtual machines that can evaluate Erlang functions.

In Erlang:

  • Creating and destroying processes is very fast.
  • Sending messages between processes is very fast.
  • Processes behave the same way on all operating systems.
  • We can have very large numbers of processes.
  • Processes share no memory and are completely independent.
  • The only way for processes to interact is through message passing.

For these reasons, Erlang is sometimes called a pure message passing language.

Working with processes

Everything we know about sequential programming is still true for concurrent programming. All we have to do is to add the following primitives:

Creating a process

You can create a new process with spawn function:

Pid = spawn(Mod, Func, Args)

The new process runs in parallel with the caller. spawn returns a Pid (short for process identifier). You can use a Pid to send messages to the process.
Note that the function Func with arity length(Args) must be exported from the module Mod. When a new process is created, the latest version of the module defining the code is used.

Pid = spawn(Fun)

Creates a new concurrent process that evaluates Fun(). This form of spawn always uses the current value of the fun being evaluated, and this fun does not have to be exported from the module. The essential difference between the two forms of spawn has to do with a dynamic code upgrade.

Sending a message

Message sending is asynchronous. The sender does not wait but continues with what it was doing. To send a message to a process using this syntax:

Pid ! Message

This sends Message to the process with the identifier Pid . ! is called the send operator.

Receiving a message

When a message arrives at the process, the system tries to match it using pattern matching. To receive a message in a process use the following syntax:

receive
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
end

receive … end receives a message that has been sent to a process. In the example above the system tries to match the message against Pattern1 (with possible guard Guard1 ); if this succeeds, it evaluates Expressions1. If the first pattern does not match, it tries Pattern2, and so on. If no pattern matches, the message is saved for later processing, and the process waits for the next message.

That’s it. You don’t need threading and locking and semaphores and artificial controls.

The Shell is a process

The shell is an easy place to send and (for test purposes, at least) receive messages. The first thing to explore is the process identifier, often called a pid. The easiest pid to get is your own. In the shell you can just run the self() function:

mep@mep:~$ erl
Erlang/OTP 22 [erts-10.4.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V10.4.4 (abort with ^G)
1> self().
<0.78.0>

Send a message in the shell

Line 1 assigned the pid for the shell, retrieved with the self() function, to a variable named Pid, and then line 2 used that Pid variable to send a message containing the atom testMessage.

Eshell V10.4.4 (abort with ^G)
1> Pid = self().
<0.78.0>
2> Pid ! testMessage.
testMessage
3>

Receiving a message in shell

Let’s double what we’re receiving in the sell using receive … end. syntax

Eshell V10.4.4 (abort with ^G)
1> Pid = self().
<0.78.0>
2> Pid ! 71.
71
3> receive X->X*2 end.
142

Let’s Ping-Pong

To demonstrate what we’ve been learning so far, let’s play some ping pong with processes. First create two modules named ping (ping.erl file) and pong (pong.erl file) with the following code:

ping and pong modules for ping ponging

Now in the shell, run the following commands (compile your modules):

Eshell V10.4.4  (abort with ^G)
1> c(ping).
{ok,ping}
2> c(pong).
{ok,pong}
3>

And finally you can ping pong from either side using the start function:

3> ping:start(7).
ping pong ping pong ping pong ping pong ping pong ping pong ping pong ok

Source:

Erlang documentation

--

--