Critique of solution to an exercise from the online course

pete-erlang-questions <>
Thu Aug 4 00:15:12 CEST 2005


[Disclaimer: I have no experience with functional programming, but
I've been intrigued recently about Erlang (the poker server blog and
the comparison of yaws to apache).  I decided to investigate and
printed some of the documentation which I read on vacation last week
sitting by a pool.  In other words, please be gentle.]

I'm trying to learn Erlang and I'm doing some of the sample exercises
from the online course (linked in the documentation section of the
erlang.org site), but I was hoping someone might provide some feedback
on my solution to one of the problems.  

Here is the question:

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.

And here is my solution:

-module(ring).
-export([start/2, start/4, head/1, head/2, node/2]).

start(NumProcesses, NumTokenPasses) ->
    HeadOfRing = spawn(ring, head, [NumTokenPasses]),
    start(NumProcesses - 1, NumTokenPasses, HeadOfRing, HeadOfRing).

start(0, _NumTokenPasses, NextNode, HeadOfRing) ->
    %% After all of the processes have been spawned, send the head of
    %% the ring a message so that it can get a reference to its next
    %% node which was not known when it was spawned.
    HeadOfRing ! {next_node, NextNode};

start(NumProcesses, NumTokenPasses, NextNode, HeadOfRing) ->
    Pid = spawn(ring, node, [NumTokenPasses, NextNode]),
    start(NumProcesses - 1, NumTokenPasses, Pid, HeadOfRing).

head(NumTokenPasses) ->
    receive
        {next_node, NextNode} ->
            %%io:format("~p HeadOfRing received START token~n", [self()]),
            head(NumTokenPasses, NextNode)
    end.

head(0, _NextNode) ->
    %%io:format("~p HeadOfRing is exiting~n", [self()]),
    {done, head, self()};

head(NumTokenPasses, NextNode) ->
    %%io:format("~p HeadOfRing sending token~n", [self()]),
    NextNode ! token,
    receive
        token ->
            %%io:format("~p HeadOfRing received token~n", [self()]),
            head(NumTokenPasses - 1, NextNode)
    end.

node(0, _NextNode) ->
    %%io:format("~p Node is exiting~n", [self()]),
    {done, self()};

node(NumTokenPasses, NextNode) ->
    receive
        token ->
            %%io:format("~p Node received token~n", [self()]),
            %%io:format("~p Node sending token~n", [self()]),
            NextNode ! token,
            node(NumTokenPasses - 1, NextNode)
    end.

Aside from comments and suggestions, I'd also appreciate any ideas why
my processes aren't exiting correctly.  Things work for a while but
then things fall apart on me.

:~/work/src/erlang$ erl
Erlang (BEAM) emulator version 5.4.6 [source] [threads:0]

Eshell V5.4.6  (abort with ^G)
1> ring:start(1000, 100).
{next_node,<0.1031.0>}
2> length(processes()).
24
3> ring:start(1000, 10000).
{next_node,<0.2033.0>}
4> length(processes()).
1024
5> 


Thanks for the help.

Pete



More information about the erlang-questions mailing list