Skip to content
Lesson 1 of 7

Step 1 of 5 · Reading · ~2 min

Learn

Process Patterns

Stateful Erlang processes use tail-recursive loops. The function calls itself with new state at the end of each iteration.

-module(main).
-export([main/1]).

start() ->
    spawn(fun() -> loop(0) end).

loop(N) ->
    receive
        increment -> loop(N + 1);
        {get, From} ->
            From ! {value, N},
            loop(N);
        stop -> ok
    end.

main(_) ->
    Pid = start(),
    Pid ! increment,
    Pid ! increment,
    Pid ! increment,
    Pid ! {get, self()},
    receive
        {value, V} -> io:format("~w~n", [V])
    end.

Key points:

  • The loop/1 function is tail-recursive — Erlang optimizes this to constant stack space.
  • Each branch of receive either calls loop again (with potentially new state) or returns (terminating the process).
  • From ! Msg sends a message. self() is the current process's PID.
  • The receiver pattern-matches on a unique tag ({value, N}) to know what message to receive.

Synchronous request/reply: The "send a message including self(), then receive a reply" pattern is so common that it has a name: a synchronous call. Real Erlang code uses gen_server:call to wrap it.

Selective receivereceive only matches messages whose patterns match. Other messages stay in the mailbox:

receive
    {priority_task, T} -> handle_priority(T)
after 0 ->
    %% skip if no priority message right now
    ok
end

The after Timeout clause runs if no message arrives within Timeout ms. after 0 is non-blocking.

The trap this chapter's exercise sets. receive matches patterns, so a pattern that nothing ever sends is a deadlock, not an error. The example above replies with the tagged tuple {value, N} and matches {value, V} -- the two halves agree. If the sender instead replies with a bare integer (From ! N) while you still match {value, V}, the integer sits unread in the mailbox and receive waits forever; the grader reports a timeout rather than wrong output. Always match the shape the sender actually sends, or give receive an after Timeout -> clause so it can give up.

Up nextRecords and MapsProcess Patterns

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…