簡體   English   中英

如果Node必須具有與客戶端節點相同的模塊,那么在erlang上Spawn(Node,Fun)有什么意義呢?

[英]What is the point of Spawn(Node, Fun) on erlang, if Node has to have the same module loadable as a client node?

為什么要創建一個幻覺,您正在向遠程節點發送Fun以在新進程中執行? 如果客戶端節點必須具有相同的模塊可加載,則無論如何都將Fun定義為服務器節點。 那么為什么不只生成(Node,M,F,A),這清楚地表明你正在發送一個函數調用的定義,而不是Fun本身。

讓我們考慮兩種可能的情況

涉及模塊功能的功能

Fun = fun file:getcwd/0,
erlang:spawn(Node, Fun). 

在這種情況下, Fun確實應該可以在遠程端加載。

匿名功能

Fun = fun() -> io:format("My node is ~p~n", [node()]) end,
erlang:spawn(Node, Fun). 

它們也可以調用

總結

雖然某個功能存在一些限制,可以遠程處理,但這種形式仍然適用並且可以刪除,因為第二種情況將變得不可能

本文可能會有一些誤解

實際上,如果你為匿名函數運行erlang:fun_info ,你會看到它以AST的形式提供實現

(b@lol4t0-home)21> rp(erlang:fun_info(fun() -> io:format("My node is ~p~n", [node()]) end)). 
[{pid,<0.96.0>},
 {module,erl_eval},
 {new_index,20},
 {new_uniq,<<99,62,121,82,122,95,246,237,63,72,118,40,4,
             25,16,50>>},
 {index,20},
 {uniq,52032458},
 {name,'-expr/5-fun-3-'},
 {arity,0},
 {env,[{[],
        {eval,#Fun<shell.21.31625193>},
        {value,#Fun<shell.5.31625193>},
        [{clause,1,[],[],
                 [{call,1,
                        {remote,1,{atom,1,io},{atom,1,format}},
                        [{string,1,"My node is ~p~n"},
                         {cons,1,{call,1,{atom,1,node},[]},{nil,1}}]}]}]}]},
 {type,local}]

下面的示例顯示遠程節點可以執行從未在其上加載的代碼,甚至是對調用者節點上定義的匿名函數的調用:

在節點上

Erlang/OTP 19 [erts-8.0] [64-bit] [smp:4:4] [async-threads:10]

Eshell V8.0  (abort with ^G)
(titi@XXXXXXXX)1> net_adm:ping(toto@XXXXXXXX).
pong
(titi@XXXXXXXX)2> F = fun F(X) -> receive {plus,N} -> F(X+N); get -> io:format("state is ~p~n",[X]), F(X); stop -> bye end end. 
#Fun<erl_eval.30.52032458>
(titi@XXXXXXXX)3> G = fun() -> register(server,self()), F(0) end.
#Fun<erl_eval.20.52032458>
(titi@XXXXXXXX)4> spawn(toto@XXXXXXXX,G).
<7039.67.0>
state is 0           
state is 5           
state is 10          
(titi@XXXXXXXX)5> 

在節點托托

Erlang/OTP 19 [erts-8.0] [64-bit] [smp:4:4] [async-threads:10]

Eshell V8.0  (abort with ^G)
(toto@XXXXXXXX)1> server ! get. % will print state is 0
get
(toto@XXXXXXXX)2> server ! {plus,5}. % new state = 5
{plus,5}
(toto@XXXXXXXX)3> server ! get. % will print state is 5    
get
(toto@XXXXXXXX)4> server ! {plus,5}. % new state = 10
{plus,5}
(toto@XXXXXXXX)5> server ! get. % will print state is 10     
get
(toto@XXXXXXXX)6> server ! stop. % ends the server process    
stop
(toto@XXXXXXXX)7> server ! get. % message will fail
** exception error: bad argument
     in operator  !/2
        called as server ! get
(toto@XXXXXXXX)8> 

我還檢查了如果你替換代碼{plus,N} -> F(X+N); by {plus,N} -> F(maps:put(X,X+N,maps:new())); 調用一個未在shell啟動時加載的模塊,它也能正常工作。

編輯

閱讀評論,似乎在shell中進行測試不是正確的方法,2結論雖然:

  • 不要只依靠shell進行驗證,
  • 應該有一種方法在遠程節點上執行一個只在調用者節點上知道的代碼,因為shell可以做到這一點......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM