在Erlang中计数(如何增加变量?)

Éva*_*ult 7 erlang

我已经找到了Erlang风格的循环:带有函数的尾递归,这些函数可以获取所有"不变的变量":

%% does something, 80 bytes at a time
loop(Line, File) -> loop(Line, File, 0).
loop(Line, File, Count) -> 
    do_something(Line, Count),
    case file:read(File, 80) of
        {ok, Line2} -> loop(Line2, File, Count + 1);
        eof -> file:close(File);
        {error, Reason} -> {error, Reason}
    end.
Run Code Online (Sandbox Code Playgroud)

但是,在Erlang中增加计数器的最佳方法是什么?在大多数编程语言中,计算事物的方式是通过递增变量(即.count += 1;).Erlang的变量没有变化,因此我们必须具有创造性.幸运的是,我们有选择......

我们可以使用函数传递Counter变量,并在每次函数调用时递增它.我们可以使用进程字典来存储计数,get并将put其递增.我们可以使用ETS,即进程的本地数据存储.我们可以使用柜台流程(!!!):

loop(Count) ->                            
    receive                                   
        { incr } -> 
            loop(Count + 1);              
        { report, To } ->                     
            To ! { count, Count },            
            loop(Count)                           
    end.                                      

incr(Counter) ->
    Counter ! { incr }.

get_count(Counter) ->    
    Counter ! { report, self() },
    receive
        { count, Count } -> Count
    end.
Run Code Online (Sandbox Code Playgroud)

我确信还有其他方法,具体取决于范围.什么被认为是在Erlang中增加变量的"最佳实践"?

Gor*_*rie 10

不要使用流程字典.

您期望的"正常"循环(即for循环或a do while)通常在Erlang中的递归函数中实现,因此如果您正在递增"正常"计数器,请在函数调用中执行此操作,就像您显示顶部一样.

不要使用流程字典.

如果您错过了,我可以指出您不应该使用流程词典.

  • 另外,不要使用进程字典. (3认同)
  • 一般规则是"如果你想知道你是否应该使用流程词典,你不应该使用它"和"你知道什么时候需要它." 公平地说,虽然存在有效的流程字典使用,但据我所知,大多数都与"递增变量"无关,而是"存储流程元数据". (3认同)
  • 然而奇怪的是,流程字典几乎用在Erlang/OTP发行版的每个应用程序中.喜欢`inets`.或者`orber`.或者`docbuilder`.或者`ic`.或者`megaco`.或者`tv`.或者`cosNotification`.或者`eunit`.或者`reltool`.或者`编译器`.或者`erts`.或者`test_server`.或者`appmon`.或者`ssh`.或者``debugger`.或者`内核`.或者``gs` 或者`os_mon`.或者`pman`.或者`stdlib`.或者`percept`.或者`xmerl`.或者`asn1`.或者`mnesia`.或者`common_test`.或者`parsetools`.或`透析器`.或者......如果社区留在消息上,那么相信"无流程词典"会更容易. (2认同)
  • 哦,我同意我提供可怕的建议.我甚至不会考虑使用进程字典来增加变量.我只是觉得无意识的口头禅"不要使用流程词典"是愚蠢的,因为你知道,Erlang的核心发行版及其所有附带的库都会广泛使用它.你的措辞要好得多."如果你想知道答案是否定的"并且"你知道何时需要它",那就更有意义了. (2认同)

Luk*_*kas 4

这完全取决于您使用计数器的目的。任何全局的东西,比如 q 系统处理的消息数量,都应该使用 ets:update_counter。如果它不是全局的,我通常只是将其包含在您所示的参数中。