Erlang计数器表达式相当于C ++,而循环?

时间:2013-03-15 00:02:33

标签: erlang while-loop counter increment

是否有增量/减量运算符的等效表达式,例如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.

3 个答案:

答案 0 :(得分: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则进程崩溃。

所以是的,如果你想要一个计数器或任何改变的信息,你必须使用一个状态变量作为递归循环的参数传递。从这个角度来看,你的上一个代码是正确的,但是让我们按照你在shell中调用“call()”时会发生什么。

首先它在同一个进程中调用shell - 函数while_loop(10,0)。

10不等于0所以它立即调用while_loop(10,1)。

10不等于1所以它立即调用while_loop(10,2)。

依此类推,直到调用while_loop(10,10)。现在10 =:= 10是真的,并且此结果与案例的任何子句都不匹配,因此您收到错误并且流程崩溃。

由于你的代码不包含任何消息接收并且只是循环循环直到它崩溃,所以wole进程只需几微秒,所以看起来它立即失败。

根据您的期望,您可以想象几种类型的计数器,这里有两个例子:

-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> 

答案 1 :(得分:1)

只需递归调用while_loopCounter参数加1:

while_loop(Var, Counter + 1)

答案 2 :(得分: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).

当然,你需要在循环中做一些事情。你可以使用lambdas:

-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).