2009-11-03 85 views
3

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

此:

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

或者这样:

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

循环函数的参数具有显式的好处,因为它外面没有任何东西可以改变参数(除非你在奇怪的魔法弹跳在另一个功能,如蹦床上),但状态往往会加起来,参数与他们。

字典如何作为参数?两全其美还是两全其美?

回答

8

我建议你使用记录来存储你的循环数据。这样,如果您需要为循环数据添加新的“变量”,您只需将其添加到记录中,而无需触摸任何子句。如果你的“键”最近改变了,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的功能性质。

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

+0

说到功能性......从邮箱(即接收)中拉取消息与从过程字典中提取数据有什么不同? – Zed 2009-11-03 19:41:20

+0

好吧,如果你从代码中的邮箱中左右拖动邮件,我会认为这是一个坏主意。我猜你的评论可能与这个问题有关,这个问题主要集中在应用程序的主要消息循环(可能)上。我更通用。 – jldupont 2009-11-03 20:09:22

+1

另一点需要注意的是函数参数可以在异常情况下正常工作,但是流程字典中的值不会被恢复 - 所以要么不要混合异常处理和流程字典,要么避免流程字典。 – archaelus 2009-11-03 20:43:10

1

另一个大的缺点,使用进程字典是它成为了很多更难做,当你拥有的数据通过函数调用不通过追查。

+0

这就是我所说的“显而易见的好处,因为它外面没有东西可以改变参数”。当国家发展壮大时,我正在寻找替代方案。记录会很适合。 – Thomas 2009-11-04 16:32:49