Uma*_*mil 4 erlang fully-qualified-naming
我刚刚学会了如何在Erlang中升级模块,我知道只有使用完全限定名称的函数调用(例如.module:function())才能"重新链接"到加载到VM中的当前版本,但函数调用没有指定模块的名称不会"重新链接"到当前版本,但继续使用旧版本.
是否有关于何时使用完全限定函数调用以及何时可以通过其名称调用函数的经验法则?使用全名调用所有函数是不是一个坏主意(比如module:function())?
Erlang应用程序通常使用标准行为 gen_server和gen_fsm这样,它们已经在其内部循环中包含完全限定的函数调用,因此要处理这个问题.
但是如果出于某种原因你不得不用自己的递归消息处理循环编写自己的模块,并且你希望该模块在运行时可以升级,那么循环需要包含一个完全限定的递归调用,通常你会放置它在处理特定升级消息的代码段内,类似于 code_change/3与标准行为一起使用的回调模块中预期函数.
例如,考虑下面的循环,它类似于标准行为的循环,但大大简化:
loop(Callbacks, State) ->
{{Next, NState},DoChange} =
receive
{code_change, ChangeData} ->
{Callbacks:handle_code_change(ChangeData, State), true};
{cast,Data} ->
{Callbacks:handle_cast(Data,State), false};
{call,From,Data} ->
Result = Callbacks:handle_call(Data,State),
case Result of
{reply, Reply} ->
From ! Reply;
_ ->
ok
end,
{Reply, false};
Message ->
{Callbacks:handle_info(Message,State), false}
end,
case Next of
stop -> ok;
_ ->
case DoChange of
true -> ?MODULE:loop(Callbacks, NState);
false -> loop(Callbacks, NState)
end
end.
Run Code Online (Sandbox Code Playgroud)
该loop/2函数有两个参数:Callbacks,希望导出为特定消息调用的特定函数的回调模块的名称,以及State对循环不透明但可能对回调模块有意义的回调模块的名称.循环是尾递归的,它通过调用特定的回调函数来处理几个特定的消息,然后通过调用handle_info/2回调模块来处理任何其他消息.(如果你已经使用了标准行为,你会发现这种方法很熟悉.)回调函数返回一个Next值,并将一个新状态传递给下一个循环.如果Next是stop,我们退出循环,否则我们检查DoChange设置为的值true 仅用于代码更改消息,如果它是真的,则循环使用完全限定的调用调用自身,否则它仅使用常规调用.
如前所述,这一切都大大简化了.您需要编写自己的循环是非常罕见的,如果您这样做,还有其他重要的事情,例如您需要处理的系统消息.您最好使用标准行为.