3

我不确定如何在模块中调用本地函数,以便在代码更改后使用最新版本的代码。请参见以下示例:

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)

为什么我会收到此错误?

4

1 回答 1

4

我相信您最终需要调用函数的完全限定版本loop/0而不是add/1函数,以便加载和使用新模块。代码加载机制准备一次处理一个模块的两个运行版本,您的示例N+3是模块的第三次加载——第一个版本被强制删除。

试试这个循环:

15 loop() ->
16     receive
17         {Pid, Z} -> Pid ! add(Z)
18     end,
19     ?MODULE:loop().

我已将其更改为在下次执行loop/0.

我相信更常见的是使用reload直接显式调用主循环的消息或类似内容,以避免在每次请求时不断重新加载模块的开销。

于 2012-06-14T22:28:28.300 回答