Hey, You! Yes, You!

Leave a comment

Sometimes you have a process whose job is to do things with messages whose format you don’t know ahead of time or need to understand.  Those processes need to handle any message you send them but at the same time be able to interpret control messages without catching anything that was actually intended to be data.

For example, it’s common to send a stop message when you want the process to end itself by not recursing. If the process is forwarding messages to other processes, the stop atom is something you’d very likely encounter. Stopping on that instead of forwarding it would be a failure.

The solution is to send and receive a tuple that’s going to be interpreted very narrowly by the pattern matcher, containing the following items:

  • ?MODULE – The preprocessor macro that expands to the name of the module containing the process’ code
  • PID – The ID of the process to which the message is addressed
  • stop – Whatever else the message needs to contain. In this case, it’s a single atom.

Erlang’s guard clauses can be used to make sure that if everything else looks correct, only tuples containing the ID of this specific process will be treated as a control message:

run() ->
    receive
        { ?MODULE, PID, stop } when PID == self() -> ok;
        _AnythingElse -> process(_AnythingElse), run()
    end

This means a stop message bound for processes running other instances of this function can be processed by the process itself without causing undesired behavior.

Here’s a complete example:

-module(blogpost).
-export([start/0, run/0]).

run() ->
    receive
        { ?MODULE, PID, stop } when PID == self() ->
            io:fwrite("All done.~n");
        _AnyOtherInput ->
            io:fwrite("Got input ~w~n", [_AnyOtherInput]),
            run()
    end.

create() -> spawn(?MODULE, run, []).
input(Object, Input) -> Object ! Input.
destroy(Object) -> Object ! { ?MODULE, Object, stop }.

start() ->
    Object = create(),
    [ input(Object, Input) || Input <- [foo, bar, baz] ],
    destroy(Object).

Welcome

Leave a comment

Welcome.  This blog is a series of hints and tips for those who are learning or using the Erlang programming language.

About Me:  I’m a well-seasoned software guy who wrote his first BASIC program in the late 1970s and has since gobbled up lots of other languages and done development in everything from embedded systems with a few kilobytes of memory to large, distributed, enterprise-class systems.  I picked up Erlang in 2013 because I’d been curious about it for some time.  While I’ve been around long enough to be a bit jaded about new languages — because I have seen a lot of them come and go — I’ve found that Erlang shows all of the signs of having been developed by people with a real problem to solve and not just a need to be language purists.