我不确定如何在模块中调用本地函数,以便在代码更改后使用最新版本的代码。请参阅以下示例:
1 -module(test).
2
3 -export([start/0, call/1]).
4 -export([loop/0, add/1]).
5
6 start() ->
7 register(foo, spawn(test, loop, [])).
8
9 call(X) ->
10 foo ! {self(), X},
11 receive
12 Y -> Y
13 end.
14
15 loop() ->
16 receive
17 {Pid, Z} -> Pid ! add(Z)
18 end,
19 loop().
20
21 add(N) ->
22 N + 1.
将要更改的功能是 add/1
.为了使用最新版本的函数,add/1
(第 17 行)的调用应该是完全限定的函数调用 {Pid, Z} -> Pid ! ?MODULE:add(Z)
.当我尝试它时,我得到这个:
1> c(test).
{ok,test}
2> test:start().
true
3> test:call(1).
2
22号线改为N + 2
4> c(test).
{ok,test}
5> test:call(1).
3
22号线再次改为N + 3
6> c(test).
{ok,test}
7> test:call(1).
** exception error: bad argument
in function test:call/1 (test.erl, line 10)
为什么我会收到此错误?
我相信您最终需要调用loop/0
函数的完全限定版本而不是add/1
函数才能加载和使用新模块。代码加载机制准备同时处理模块的两个运行版本,而带有 N+3
的示例是模块的第三次加载 - 并且第一个版本被强制删除。
请尝试以下循环:
15 loop() ->
16 receive
17 {Pid, Z} -> Pid ! add(Z)
18 end,
19 ?MODULE:loop().
我已经更改了它以在下次执行loop/0
时重新加载最新版本。
我认为更常见的是使用 reload
消息或类似消息直接显式调用主循环,以避免在每个请求上不断重新加载模块的开销。