Erlang代码更改和本地函数调用

Erlang代码更改和本地函数调用,erlang,gen-server,hotswap,Erlang,Gen Server,Hotswap,我不知道如何调用模块中的本地函数,以便在代码更改后使用最新版本的代码。请参见以下示例: 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

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

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?模块:添加(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)

为什么会出现此错误?

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

尝试以下循环:

15 loop() ->
16     receive
17         {Pid, Z} -> Pid ! add(Z)
18     end,
19     ?MODULE:loop().
我已将其更改为在下次执行
循环/0
时重新加载最新版本


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

它可以工作,谢谢!所以我猜
循环/1
没有改变,在第三次改变之后,它被擦除了。但是我仍然不明白为什么
?MODULE:loop()
导致加载新版本的
add/1
,为什么
?MODULE:add()
没有对
loop/1
执行相同的操作。我认为诀窍在于
?MODULE:add()
将执行到完成,然后该模块将消失。不要忘记,您可能有数千个进程在这个模块中执行,您不想从它们下面全部更改代码——只有那些想要更改的