2011-05-24 116 views

回答

7

Here是一篇關於「將樂趣傳遞給其他Erlang節點」的有趣文章。簡要地恢復它:

[...]正如你可能知道,Erlang分佈 通過發送方面的二進制編碼 工程;所以發送一個樂趣也是 基本上是通過使用 erlang:term_to_binary/1對其進行編碼完成的;將 生成的二進制傳遞給另一個節點,然後使用 再次對其進行解碼,使用 erlang:binary_to_term/1。 對於大多數數據類型,這是非常明顯的 ;但是 如何用於函數對象?

當你編碼一個有趣的東西時,編碼的 只是對函數的引用,而不是函數的實現。 [...]

函數的定義不會傳遞;如果模塊在那裏,就足夠的信息來重新創建其他節點的樂趣。

[...]如果包含fun的模塊尚未加載,並且目標節點以交互模式運行;然後嘗試使用常規模塊加載機制(包含在模塊error_handler中)加載模塊;然後它試圖查看在所述模塊中是否有給定ID的樂趣。但是,只有在嘗試應用該功能時纔會發生這種情況。

[...] [...]如果你從來沒有嘗試應用這個函數,那麼沒有什麼不好的事情發生。樂趣可以傳遞給另一個節點(它有問題的模塊/樂趣),然後每個人都很開心。 也許目標節點有一個裝載了所述名稱的模塊,但可能是不同的版本;然後很可能會有不同的MD5校驗和,那麼如果您嘗試應用它,則會出現錯誤badfun。

我建議你閱讀整篇文章,因爲它非常有趣。

5

您可以發送任何有效的Erlang術語。雖然發送樂趣時你必須小心。什麼好玩的引用模塊內部的功能需要與模塊到目標節點上存在的工作:

([email protected])9> rpc:call([email protected], erlang, apply, 
         [fun io:format/1, ["Hey!~n"]]). 
Hey! 
ok 
([email protected])10> mymodule:func("Hey!~n"). 
5 
([email protected])11> rpc:call([email protected], erlang, apply, 
         [fun mymodule:func/1, ["Hey!~n"]]). 
{badrpc,{'EXIT',{undef,[{mymodule,func,["Hey!~n"]}, 
         {rpc,'-handle_call_call/6-fun-0-',5}]}}} 

在這個例子中,io存在兩個節點上和它的作品從io發送功能的樂趣。但是,mymodule僅存在於第一個節點上,並且fun在另一個節點上調用時會生成undef異常。

+0

匿名函數呢? – Federico 2011-05-24 19:24:42

+0

如果你認爲你的名字是匿名的,那麼它有同樣的問題。即它定義的模塊必須存在於遠程節點上。 – Lukas 2011-05-24 20:10:13

2

至於匿名功能,看起來他們可以發送和按預期工作。

T1 @本地:

([email protected])7> register(shell, self()). 
true 
([email protected])10> A = me, receive Fun when is_function(Fun) -> Fun(A) end. 
hello me you 
ok 

T2 @本地:

([email protected])11> B = you. 
you 
([email protected])12> Fn2 = fun (A) -> io:format("hello ~p ~p~n", [A, B]) end. 
#Fun<erl_eval.6.54118792> 
([email protected])13> {shell, '[email protected]'} ! Fn2. 

我加入覆蓋邏輯建立在了Riak核心的應用程序,以及合併結果的聚集可如果匿名函數不能在消息中使用,就很棘手。

還檢查了riak_kv/src/riak_kv_coverage_filter.erl

riak_kv可能會使用它來filter結果,我猜。