我在Erlang中实现了一个简单的汽车流程:
-module(cars).
-compile(export_all).
-record(state, {count=1}).
make_car() ->
spawn_link(fun() -> car_proc(#state{}) end).
car_proc(S) ->
receive
{idle, X} ->
io:format("idling for ~p second(s)~n", [X]),
timer:sleep(X*1000);
{move, {X,Y}} ->
io:format("move; x=~p, y=~p~n", [X,Y]);
{stop, Reason} ->
X = S#state.count,
io:format("stopped with count ~p because ~p~n", [X+1, Reason])
end,
X = S#state.count,
car_proc(S#state{count=X+1}).
我可以让它空闲,但如果我连续两次调用空闲,它会中断:
59> C = cars:make_car().
<0.207.0>
60> C!{idle,1}.
idling for 1 second(s)
{idle,1}
61> C!{idle,1}.
idling for 1 second(s)
{idle,1}
62>
=ERROR REPORT==== 9-Apr-2013::00:00:00 ===
Error in process <0.207.0> with exit value: {{badmatch,2},[{cars,car_proc,1,[{file,"cars.erl"},{line,20}]}]}
** exception error: no match of right hand side value 2
in function cars:car_proc/1 (cars.erl, line 20)
为什么?
答案 0 :(得分:4)
错误发生在第20行,即
X = S#state.count
发生这种情况是因为模式匹配失败。变量'X'已在此行中定义,其值为1,因为它已在接收块中确定:
receive
{idle, X} ->
在Erlang中,变量值只能定义一次。当您发送消息{idle,1}时,第一次X变为1并且S#state.count的默认值为1.因此,在这种情况下,'X'与S#state.count匹配。当你发送{idle,1}秒时X是1而S#state.count是2(即X和S#state.count不相等)。所以你在模式匹配中得到错误。您可以使用另一个变量来避免此问题。改变最后两行
X = S#state.count,
car_proc(S#state{count=X+1}).
到
Count = S#state.count,
car_proc(S#state{count=Count+1}).
快乐!