0

インクリメント/デクリメント演算子に相当する式はありますcounter++か?また、これを適切に行う方法も疑問に思いますか?

-module(whileloop).
-export([call/0, while_loop/2]).

call() ->
    while_loop(10,0).

while_loop(Var,Counter) ->  
    case Var =:= Counter of
        false ->
            Counter += 1,
            whileloop(Var);
    end.

編集:

 -module(whileloop).
-export([call/0, while_loop/2]).

call() ->
    while_loop(10,0).

while_loop(Var, Counter) -> 
    case Var =:= Counter of
        false ->            
            while_loop(Var,Counter + 1)
    end.
4

3 に答える 3

3

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> 
于 2013-03-15T05:47:47.187 に答える
1

引数を1つ増やしwhile_loopて再帰的に呼び出します。Counter

while_loop(Var, Counter + 1)
于 2013-03-15T00:16:07.073 に答える
1

Var =:= Counter編集したバージョンには、いつクラッシュするかという句がありません。また、関数句ではパターンマッチングを使用することをお勧めします。

-module(whileloop).
-export([call/0, while_loop/2]).

call() ->
    while_loop(10,0).

while_loop(Var, Var) ->
    ok;
while_loop(Var, Counter) -> 
    while_loop(Var, Counter + 1).

そしてもちろん、ループ内で何かをする必要があります。そのためにラムダを使用できます:

-module(whileloop).
-export([call/0, while_loop/2]).

call() ->
    while_loop(10, 0, fun(Counter) -> io:format("Counter: ~p~n", [Counter]) end).

while_loop(Var, Var, _) ->
    ok;
while_loop(Var, Counter, Fun) ->
    Fun(Counter),
    while_loop(Var, Counter + 1).
于 2013-03-15T07:55:46.363 に答える