3
我相信我在某处读过关于热重新加载时使用spawn/1
和spawn/3
的区别,但我无法找到有关该主题的任何完整信息。所以我想知道实际上是否有区别,如果有,那么它是什么?一些例子会很棒。谢谢。spawn/1和spawn/3之间的差异
我相信我在某处读过关于热重新加载时使用spawn/1
和spawn/3
的区别,但我无法找到有关该主题的任何完整信息。所以我想知道实际上是否有区别,如果有,那么它是什么?一些例子会很棒。谢谢。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
我们可以开始一个过程,每次我们发送: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
现在,如果我们修改模块来代替打印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
当我们告诉只是过程中的“刷新”,通过使该模块的完全合格的号召,做我们得到的新版本:
iex(7)> send p, :reload
:reload
iex(8)> send p, :foo
foo 2
:foo
当然,如果你使用spawn/1
与一个功能,只是一个完全合格的电话,差异消失:
spawn(fn -> Foo.print_foo end)
我不能要求更好的解释,谢谢。 – JustMichael