【问题标题】:Process dictionary or loop parameters?处理字典或循环参数?
【发布时间】:2009-11-04 17:45:31
【问题描述】:

我什么时候应该使用进程范围的字典,我的进程状态什么时候应该在循环函数的参数中?

这个:

loop() ->
  receive
     {From, subscribe} ->
       put(listeners, [From|get(listeners)]),
       ?MODULE:loop()
  end.

或者这个:

loop(Listeners) ->
  receive
    {From, subscribe} ->
       ?MODULE:loop([From|Listeners])
  end.

?

循环函数的参数具有明确的好处,因为它之外的任何东西都不能改变参数(除非你在另一个函数上做奇怪的魔法弹跳,比如蹦床),但是状态往往会累加,并且参数和他们一起。

将字典作为参数怎么样?两全其美还是两全其美?

【问题讨论】:

    标签: erlang


    【解决方案1】:

    我建议您使用记录来存储循环数据。这样,如果您需要在循环数据中添加新的“变量”,您只需将其添加到记录中,而无需触及任何子句。只有当您的“键”最近发生变化时,Dict 才是更好的选择,这在循环数据的情况下不太可能。

    -record(state, {
               listeners = [],
               new_var   = undefined,
               new_var2  = ""
               ...
            }).
    
    init() ->
      loop(#state{}).
    
    loop(State) ->
      receive
        {From, subscribe} ->
           loop(State#state{listeners = [From|State#state.listeners]});
        somethingelse ->
           do_nothing(),
           loop(State)
      end.
    

    【讨论】:

      【解决方案2】:

      使用流程字典的主要缺点与可能的副作用有关:当您开始大量使用流程字典时,跟踪可能的副作用会更加困难。

      例如,假设您在函数“X”中并开始从进程字典中提取数据,那么您实际上是在违背 Erlang 的函数性质。

      但是,嘿,在某些时候您需要访问更大的数据存储,不是吗?重点是:尽量隔离对进程字典的访问。

      【讨论】:

      • 说到功能性质……从功能上来说,从邮箱中提取消息(即接收)与从进程字典中提取数据有什么不同?
      • 好吧,如果您在代码中从邮箱中左右拉出消息,我认为这是个坏主意。我猜您的评论可能与问题围绕(可能)应用程序的主消息循环这一事实有关。我更一般。
      • 要记住的另一点是,函数参数在存在异常的情况下可以正常工作,但不会恢复进程字典中的值——所以要么不要混合异常处理和进程字典,要么更好的是,避免使用进程字典。
      【解决方案3】:

      使用流程字典的另一个大缺点是,当您拥有的数据没有通过函数调用传入时,进行跟踪变得更加困难。

      【讨论】:

      • 这就是我所说的“明确的好处是它之外的任何东西都不能改变参数”。当国家不断发展壮大时,我一直在寻找替代方案。记录将非常适合。
      猜你喜欢
      • 2014-04-15
      • 2021-10-03
      • 1970-01-01
      • 2012-04-03
      • 2023-02-26
      • 2020-02-10
      • 1970-01-01
      • 2015-10-13
      • 2017-03-09
      相关资源
      最近更新 更多