在 Erlang 中使用完全限定的函数调用?

Using fully qualified function calls in Erlang?

我刚刚学会了如何在 Erlang 中升级模块,我知道只有使用完全限定名称(例如 module:function())的函数调用才能 "relinked" 加载到当前版本进入 VM,但未指定模块名称的函数调用不会 "relinked" 到当前版本,而是继续使用旧版本。

对于何时使用完全限定的函数调用以及何时可以仅通过函数名称调用函数是否有经验法则?使用全名(如 module:function())调用所有函数是个坏主意吗?

Erlang 应用程序通常使用 gen_server and gen_fsm 等标准行为,这些行为已经在其内部循环中包含完全限定的函数调用,因此会处理这个问题。

但是,如果出于某种原因,您觉得有必要编写自己的模块,使其具有自己的递归消息处理循环,并且您希望该模块在运行时可升级,则该循环需要包含完全限定的递归调用,并且通常您可以将它放在处理特定升级消息的代码部分中,类似于 code_change/3 function 预期用于标准行为的回调模块。

例如,考虑下面的循环,它与标准行为的循环类似但大大简化了:

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.

loop/2 函数有两个参数:Callbacks,预期导出为特定消息调用的特定函数的回调模块的名称,以及 State,它对循环但大概对回调模块有意义。该循环是尾递归的,它通过调用特定的回调函数来处理几个特定的​​消息,然后通过调用回调模块中的 handle_info/2 来处理任何其他消息。 (如果您使用过标准行为,您会发现这种方法很熟悉。)回调函数 return 一个 Next 值,以及一个要传递给下一个循环的新状态。如果 Nextstop,我们退出循环,否则我们检查 DoChange 的值,它设置为 true 仅用于代码更改消息,如果它是 true循环使用完全限定的调用调用自身,否则它只使用常规调用。

如前所述,这一切都大大简化了。您很少需要编写自己的循环,如果您这样做,还有其他重要的事情没有在这里显示,例如 system messages 您需要处理。您最好使用标准行为。