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 未绑定,则它将 B 的值绑定到 A;
  • 如果 A =:= B 什么都没做,则过程继续;
  • 如果 A =/= B 则进程崩溃。

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

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

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

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

依此类推,直到它调用 while_loop(10,10)。现在 10 =:= 10 为真,并且这个结果与 case 的任何子句都不匹配,所以你得到一个错误并且进程崩溃。

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

根据您的期望,您可以想象几种类型的计数器,这里有 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

您编辑的版本没有子句 whenVar =:= 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).

当然,您需要在循环内做一些事情。您可以为此使用 lambda:

-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 回答
1

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

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