我相信我已经读过某个地方,使用spawn/1和spawn/3热重新加载之间有区别,但我找不到关于这个主题的任何完整信息.所以我想知道是否真的有差异,如果有,那么它是什么?一些例子会很棒.谢谢.
两者之间的区别在于spawn/1进行本地函数调用,同时spawn/3进行"完全限定"函数调用.
当您加载新版本的模块时,旧版本仍然存在,并且旧版本中执行的任何进程都会继续执行此操作.例外情况是,如果进程执行"完全限定"函数调用,包括模块名称:在这种情况下,始终使用最新版本的代码.
例如,使用此模块:
defmodule Foo do
def start_loop do
spawn(fn -> loop end)
end
def loop do
receive do
:foo ->
spawn &print_foo/0
loop
:reload ->
Foo.loop
end
end
def print_foo do
IO.puts "foo 1"
end
end
Run Code Online (Sandbox Code Playgroud)
我们可以启动一个流程,每次发送:foo到它时,它都会产生另一个打印过程foo 1:
iex(1)> c("foo.ex")
[Foo]
iex(2)> p = Foo.start_loop
#PID<0.68.0>
iex(3)> send p, :foo
foo 1
:foo
iex(4)> send p, :foo
foo 1
:foo
Run Code Online (Sandbox Code Playgroud)
现在,如果我们修改模块以进行打印foo 2,并重新编译并重新加载它,则不会立即进行更改:
iex(5)> c("foo.ex")
warning: redefining module Foo (current version loaded from Elixir.Foo.beam)
foo.ex:1
[Foo]
iex(6)> send p, :foo
foo 1
:foo
Run Code Online (Sandbox Code Playgroud)
只有当我们告诉流程"重新加载"时,通过对模块进行完全限定的调用,我们才能获得新版本:
iex(7)> send p, :reload
:reload
iex(8)> send p, :foo
foo 2
:foo
Run Code Online (Sandbox Code Playgroud)
当然,如果你使用spawn/1一个只进行完全限定的调用的函数,差异就会消失:
spawn(fn -> Foo.print_foo end)
Run Code Online (Sandbox Code Playgroud)