2016-08-22 4 views
3

Ich glaube, ich habe irgendwo gelesen, dass es einen Unterschied zwischen spawn/1 und spawn/3 gibt, wenn es um heißes Nachladen geht, aber ich kann keine vollständigen Informationen zu diesem Thema finden. Also frage ich mich, ob es tatsächlich einen Unterschied gibt und wenn ja, was ist es dann? Ein Beispiel wäre großartig. Vielen Dank.Unterschied zwischen spawn/1 und spawn/3

Antwort

5

Der Unterschied zwischen den beiden ist, dass spawn/1 einen lokalen Funktionsaufruf macht, während spawn/3 einen "voll qualifizierten" Funktionsaufruf macht.

Wenn Sie eine neue Version eines Moduls laden, bleibt die alte Version erhalten, und jeder Prozess, der in der alten Version ausgeführt wurde, macht dies weiterhin. Die Ausnahme ist, wenn der Prozess einen "vollqualifizierten" Funktionsaufruf ausführt, einschließlich des Modulnamens: In diesem Fall wird immer die neueste Version des Codes verwendet.

Zum Beispiel mit diesem Modul:

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 

wir einen Prozess starten kann, und jedes Mal, wenn wir :foo, um es zu senden, laicht es einen weiteren Prozess, der foo 1 druckt:

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 

Jetzt, Wenn wir das Modul so modifizieren, dass es stattdessen foo 2 druckt, neu kompiliert und neu lädt, gibt es keine sofortige Änderung:

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 

Nur wenn wir sagen, um den Prozess zu „Neu laden“, um einen vollständig qualifizierten Aufruf an das Modul zu machen, haben wir die neue Version erhalten:

iex(7)> send p, :reload 
:reload 
iex(8)> send p, :foo 
foo 2 
:foo 

Natürlich, wenn Sie spawn/1 verwenden mit eine Funktion, die nur einen voll qualifizierten Anruf macht, der Unterschied verschwindet:

spawn(fn -> Foo.print_foo end) 
+0

Ich könnte nicht für eine bessere Erklärung bitten, danke. – JustMichael