[erlang-questions] How to do counters?

Alpar Juttner <>
Fri Jun 26 08:02:45 CEST 2009


On Thu, 2009-06-25 at 21:45 -0400, Jarrod Roberson wrote:
> On Thu, Jun 25, 2009 at 7:10 PM, Vance Shipley <> wrote:
> 
> > On Thu, Jun 25, 2009 at 06:29:26PM -0400, Jarrod Roberson wrote:
> > }  what do you mean by "internal state" I don't understand how a process
> > would
> > }  store any mutable state
> >
> > http://erlang.org/doc/man/gen_server.html#Module:handle_call-3
> >
> > The last argument in gen_server/gen_fsm callback functions
> > is State.  It's "mutable" by the fact that the return value
> > includes NewState.
> >
> > In functional programming everything a function needs to know
> > is passed in as arguments.  Tail recursion keeps the balls in
> > the air.
> >
> >        loop(State) ->
> >                ...
> >                loop(NewState).
> >
> >
> > --
> >         -Vance
> >
> 
> I still don't see how this is supposed to work.
> If I do tail recursion, how do I return anything, if the loop(NewState)
> needs to be the last thing I do?
> 
> If I have functions inc() dec() and current() which should return the
> current value of the counter, how do all these functions share state?

You have a single registered process which runs the loop(). 
The function inc() and dec() send messages to this process. These
messages instruct loop() to increase/decreace its counter state. The
function current() sends a query message and also its own pid in order
that loop() will be able to send the current value back.

Look at the code below. First, start it with counter:start(), then
counter:inc(), counter:dec() and counter:current() will do what you
want.

Regards,
Alpar


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  counter.erl
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-module(counter).

-export([inc/0,dec/0,current/0,start/0,loop/1]).

inc() ->
    global_counter ! inc_counter,
    ok.

dec() ->
    global_counter ! dec_counter,
    ok.

current() ->
    global_counter ! {get_counter, self()},
    receive
        { counter_value, Cnt } ->
            Cnt
    end.
        
start() ->
    register(global_counter,spawn(counter,loop,[0])),
    ok.

loop(Counter) ->
    receive
        inc_counter ->
            NewCounter = Counter+1;
        dec_counter ->
            NewCounter = Counter-1;
        {get_counter, Pid} ->
            Pid ! { counter_value, Counter },
            NewCounter = Counter
    end,
    loop(NewCounter).



More information about the erlang-questions mailing list