C + = 1の意味は、Cの値を変更することです。次の結果しか得られないため、Erlangでは意味がありません。
1> C = C+1.
* 1: variable 'C' is unbound
C = 1.
1
3> C = C+1.
** exception error: no match of right hand side value 2
「A=B」は、Bの値をAに割り当てることを意味するのではなく、AをBに対して「パターンマッチ」することを意味することに注意してください。
- Aがバインドされていない場合、AはBの値にバインドされます。
- A =:= B何も行われない場合、プロセスは続行されます。
- A = / = Bの場合、プロセスはクラッシュします。
そうです、カウンターや変更する情報が必要な場合は、再帰ループの引数として渡される状態変数を使用する必要があります。この観点から、最後のコードは正しいですが、シェルで「call()」を呼び出したときに何が起こるかを追跡しましょう。
最初に、同じプロセス(シェル)で関数while_loop(10,0)を呼び出します。
10は0と等しくないため、すぐにwhile_loop(10,1)を呼び出します。
10は1と等しくないため、すぐにwhile_loop(10,2)を呼び出します。
while_loop(10,10)が呼び出されるまで続きます。ここで、10 =:= 10が真であり、この結果はケースのどの句とも一致しないため、エラーが発生し、プロセスがクラッシュします。
コードには受信メッセージが含まれておらず、クラッシュするまでループをループするだけなので、プロセス全体は数マイクロ秒しかかからないため、すぐに失敗するように見えます。
あなたが期待するものに応じて、あなたはいくつかのタイプのカウンターを想像することができます、ここに2つの例があります:
-module(counter).
-compile(export_all).
% one counter that help you to count some events
% interface
start_c1(End) when is_integer(End) ->
spawn(?MODULE,counter1,[End]).
start_link_c1(End) when is_integer(End) ->
spawn_link(?MODULE,counter1,[End]).
inc_c1(Pid) when is_pid(Pid) ->
Ref = make_ref(),
Pid ! {inc,self(),Ref},
receive
{Ref,done} -> done;
{Ref,V} -> V
after 1000 ->
{error,no_response}
end.
value_c1(Pid) when is_pid(Pid) ->
Ref = make_ref(),
Pid ! {get_value,self(),Ref},
receive
{Ref,V} -> V
after 1000 ->
{error,no_response}
end.
stop_c1(Pid) when is_pid(Pid) ->
Pid ! stop.
% the counter
counter1(End) -> counter1_loop(End,0).
counter1_loop(End,V) ->
receive
{inc,Pid,Ref} when V =/= done ->
NewV = case V+1 of
End -> done;
Nv -> Nv
end,
Pid ! {Ref,NewV},
counter1_loop(End,NewV);
{inc,Pid,Ref} ->
Pid ! {Ref,done},
counter1_loop(End,done);
{get_value,Pid,Ref} ->
Pid ! {Ref,V},
counter1_loop(End,V);
stop ->
ok
end.
% One kind of timeout that execute something after a while -
% note it exists a similar one in the library
start_after(T,M,F,A) when is_integer(T), is_list(A) ->
Ref = make_ref(),
{Ref,spawn(?MODULE,after_receive,[T,M,F,A,self(),Ref])}.
cancel_after(P) when is_pid(P) ->
P ! cancel.
% the counter
after_receive(T,M,F,A,Pid,Ref) ->
receive
{cancel,Ref} -> Pid ! {after_receive,Ref,cancelled}
after T ->
Pid ! {after_receive,Ref,done},
apply(M,F,A)
end.
そしてここでそれらを使用する方法:
1> c("../src/counter").
{ok,counter}
2> {Ref,P} = counter:start_after(5000,io,format,["This is the end!" ]).
{#Ref<0.0.0.29>,<0.33.0>}
This is the end!3>
3> {Refa,Pa} = counter:start_after(50000,io,format,["This is the end!" ]).
{#Ref<0.0.0.34>,<0.35.0>}
4> Pa ! {cancel,Refa}.
{cancel,#Ref<0.0.0.34>}
5> flush().
Shell got {after_receive,#Ref<0.0.0.29>,done}
Shell got {after_receive,#Ref<0.0.0.34>,cancelled}
ok
6> P1 = counter:start_c1(5).
<0.52.0>
7> counter:inc_c1(P1).
1
8> counter:inc_c1(P).
{error,no_response}
9> counter:inc_c1(P1).
2
10> counter:inc_c1(P1).
3
11> counter:value_c1(P1).
3
12> counter:inc_c1(P1).
4
13> counter:inc_c1(P1).
done
14> counter:value_c1(P1).
done
15> counter:inc_c1(P1).
done
16> counter:stop_c1(P1).
stop
17> counter:inc_c1(P1).
{error,no_response}
18>