I am new to functional programming and just switched from haskell (Didn't like it much) to erlang (quite fond of it). As I am learning as an autodidact, I stumbled over [these Exercises](http://www.erlang.org/course/exercises.html) and started doing them.

I came as far as this problem:

> 
> 1. Write a function which starts 2 processes, and sends a message M
>  times forewards and backwards between them. After the messages have
>  been sent the processes should terminate gracefully.
> 
> 
> 

I resolved it like this and it works (maybe it can be done better; any comment highly appreciated):

```
-module (concur).
-export ( [pingpong/1, pingpong/2] ).

pingpong (Msg, TTL) ->
    A = spawn (concur, pingpong, ["Alice"] ),
    B = spawn (concur, pingpong, ["Bob"] ),
    B ! {A, TTL * 2, Msg}.

pingpong (Name) ->
    receive
        {From, 1, Msg} -> 
            io:format ("~s received ~p and dying.~n", [Name, Msg] ),
            exit (From);
        {From, TTL, Msg} ->
            io:format ("~s received ~p.~n", [Name, Msg] ),
            From ! {self (), TTL - 1, Msg},
            pingpong (Name)
    end.

```

The real problem is the next exercise:

> 
> 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.
> 
> 
> 

As I am not sending the message back to its originator, but to the next node in the chain, I somehow have to pass to the sending process the process of the recipient. So I imagined that the function would look something like this:

```
pingCircle (Name, Next) ->
...
    receive {TTL, Msg} -> Next ! {TTL - 1, Msg}
...

```

But how do I start this whole thing. When I spawn the first function in the circle, I still haven't spawned the next node and hence I cannot pass it as an argument. So my naive approach doesn't work:

```
First = spawn (concur, pingCirle, ["Alice", Second] ),
Second = spawn (concur, pingCirle, ["Bob", Third] ),
...

```

Also the approach of passing the spawn call of the next node recursively as a parameter to it predecessor, doesn't solve the problem how to close the circle, i.e. passing the last node to the first.

**The question is:**
How can I build this circle?

**EDIT:**

Thanks to your great answers, I managed to what I intended. Hence this question is solved.

One possible solution is:

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

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

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

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

```

Here is my [peer review link](https://codereview.stackexchange.com/questions/3745/erlang-concurrency-in-circles).