[erlang-questions] How to do counters?

Michael Truog mjtruog@REDACTED
Tue Jun 30 06:27:43 CEST 2009


Richard O'Keefe wrote:
>
> On Jun 30, 2009, at 11:56 AM, Witold Baryluk wrote:
>> You can also use parametrized modules:
>
> You _can_, but why use an experimental and moderately
> heavyweight feature when the *fundamental* mechanisms
> of the language are perfectly adequate?
>
I am not trying to justify the usage of parametrized modules, but they
are a bit new to me, so I find their usage interesting.  I have an
example that attempts to be object-oriented with a tuple list of functions:

-module(counter).
-export([new/0]).

new() ->
    class:new([
        {increment, fun(State) -> State + 1 end},
        {decrement, fun(State) -> State - 1 end},
        {reset,     fun(_) -> 0 end},
        {read,      fun(State) -> State end}
    ], 0).

-module(class, [Class]).
-export([new/2, call/1]).

new(Functions, State) when is_list(Functions) ->
    class_impl:new(Functions, State).

call(Method) when is_atom(Method)  ->
    ipc(Class, {call, Method}).

ipc({class, Pid}, Msg) when is_pid(Pid) ->
    Pid ! {Msg, self()},
    receive {Pid, Result} -> Result end.

-module(class_impl).
-export([new/2]).

new(Functions, State) when is_list(Functions) ->
    class:instance({class, spawn(fun() -> loop(Functions, State) end)}).

loop(Functions, State) when is_list(Functions) ->
    receive {{call, Method}, Sender} ->
        case lists:keyfind(Method, 1, Functions) of
            false ->
                Sender ! {self(), badfun};
            {Method, F} ->
                NewState = F(State),
                Sender ! {self(), NewState},
                loop(Functions, NewState)
        end
    end.


Erlang R13B01 (erts-5.7.2) [source] [64-bit] [smp:4:4] [rq:4]
[async-threads:0] [kernel-poll:false]

Eshell V5.7.2  (abort with ^G)
1> c(class_impl).
{ok,class_impl}
2> C = counter:new().
{class,{class,<0.40.0>}}
3> C:call(read).
0
4> C:call(increment).
1
5> C:call(increment).
2
6> C:call(increment).
3
7> C:call(increment).
4
8> C:call(decrement).
3
9> C:call(decrement).
2
10> C:call(decrement).
1
11> C:call(decrement).
0
12> C:call(decrement).
-1
13> C:call(reset).   
0



More information about the erlang-questions mailing list