Erlang的变量不可变,这就意味着不能使用变量来实现计数器,然而可以用一个进程来模拟一个计数器。即使用一个loop循环来模拟一个状态,当接受到add消息时,loop的参数就+1,这样就模拟了一个状态,详细代码如下:
-module(counter).
-export([start/1,add/1,value/1]).
-export([init/1]).
start(InitCount) ->
spawn_link(?MODULE, init, [InitCount]).
add(Name) -> call({add, Name}).
value(Name) -> call({value, Name}).
call({Request, Name}) ->
Name ! {request, Request, self()},
receive
{reply, Reply} -> Reply
end.
init(Count) ->
receive
{request, add, From} ->
reply(From, Count+1),
init(Count+1);
{request, value, From} ->
reply(From, Count),
init(Count)
end.
reply(From, Count) ->
From ! {reply, Count}.
- 15> Counter = counter:start(3).
-
<0.62.0>
-
16> counter:value(Counter).
-
3
-
17> counter:add(Counter).
-
4
-
18> counter:add(Counter).
-
5
上面为计数器的使用方法,Counter相当于计数器的名字,实际上为计数器的Pid,计数器+1的操作都是通过向该进程发送消息来实现的。上述的代码中没有用到register方法,意味着不会与其它进程使用的计数器发生冲突。
这里的一个问题是,进程的状态是保存在哪里的?
答案是init函数,init函数是个尾递归函数,当接收到其它进程发送的消息时,如add,那么init(Count)会首先把Count+1返回给发送消息的进程,然后调用init(Count+1),等待下个消息。因此进程的状态在拥有receive...end块的函数的参数中。
阅读(3191) | 评论(0) | 转发(0) |