[英]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結論雖然:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.