Erlang concurrency in circles I am new to erlang (2 days to be honest) and I would highly appreciate some peer review. I am doing these exercises and was a bit stuck at this point:


  2) Write a function which starts N processes in a ring, and sends a
  message M times around all the processes in the ring. After the
  messages have been sent the processes should terminate gracefully.


With some help from SO, I came up with a working solution, but I am not sure about its quality in any aspect: Language comprehension, Coding style, Efficiency, etc.

I will be grateful for any comment you have.

-module (concur).
-export ( [pingCircle/3, pingCircle/2] ).

pingCircle (Names, Message, TTL) -&gt;
    Processes = lists:map (fun (Name) -&gt; spawn (?MODULE, pingCircle, [Name, nobody] ) end, Names),
    ProcessPairs = lists:zip (Processes, rot1 (Processes) ),
    lists:map (fun ( {Process, Recipient} ) -&gt; Process ! {setRecipient, Recipient} end, ProcessPairs),
    Circle = lists:map (fun ( {Process, _} ) -&gt; Process end, ProcessPairs),
    hd (Circle) ! {Message, TTL - 1, lists:last (Circle) }.

rot1 ( [] ) -&gt; [];
rot1 ( [Head | Tail] ) -&gt; Tail ++ [Head].

pingCircle (Name, Recipient) -&gt;
    receive
        {setRecipient, NewRecipient} -&gt;
            pingCircle (Name, NewRecipient);
        {Message, 0, Originator} -&gt;
            io:format ("~s received ~p with TTL 0 and dying.~n", [Name, Message] ),
            if
                Originator == self () -&gt; io:format ("All dead.~n");
                true -&gt; Recipient ! {Message, 0, Originator}
            end;
        {Message, TTL, Originator} -&gt;
            io:format ("~s received ~p with TTL ~p.~n", [Name, Message, TTL] ),
            if
                Originator == self () -&gt; Recipient ! {Message, TTL - 1, Originator};
                true -&gt; Recipient ! {Message, TTL, Originator}
            end,
            pingCircle (Name, Recipient)
    end.
You can replace 

spawn (?MODULE, pingCircle, [Name, nobody] )


with

spawn (fun() -&gt; pingCircle(Name, nobody) end)


This action allows do not export pingCircle/2 from the module.
It is also recommended to use spawn_link instead of spawn, because it helps to avoid lost processes.