主に、Erlang の分散セットアップで関数をメッセージで送信できるかどうかを知りたいです。
マシン 1:
F1 = Fun()-> hey end,
gen_server:call(on_other_machine,F1)
マシン 2:
handler_call(Function,From,State) ->
{reply,Function(),State)
それは理にかなっていますか?
主に、Erlang の分散セットアップで関数をメッセージで送信できるかどうかを知りたいです。
マシン 1:
F1 = Fun()-> hey end,
gen_server:call(on_other_machine,F1)
マシン 2:
handler_call(Function,From,State) ->
{reply,Function(),State)
それは理にかなっていますか?
「fun を他の Erlang ノードに渡す」についての興味深い記事があります。簡単に再開するには:
[...] ご存じかもしれませんが、Erlang ディストリビューションは用語のバイナリ エンコーディングを送信することによって機能します。したがって、fun の送信も基本的には erlang:term_to_binary/1; を使用してエンコードすることによって行われます。結果のバイナリを別のノードに渡し、erlang:binary_to_term/1.[...] を使用して再度デコードします。これはほとんどのデータ型で明らかです。しかし、関数オブジェクトに対してはどのように機能するのでしょうか?
fun をエンコードする場合、エンコードされるのは関数の実装ではなく、関数への参照だけです。[...]
[...]関数の定義は渡されません。モジュールがそこにある場合、他のノードで楽しみを再現するのにちょうど十分な情報です。
[...] fun を含むモジュールがまだロードされておらず、ターゲット ノードがインタラクティブ モードで実行されている場合。次に、通常のモジュール読み込みメカニズム (モジュール error_handler に含まれる) を使用して、モジュールの読み込みが試行されます。次に、指定された id の fun がそのモジュールで利用できるかどうかを確認しようとします。ただし、これは関数を適用しようとしたときに遅延してのみ発生します。
[...] 関数を適用しようとしない場合、悪いことは何も起こりません。fun は別のノード (問題のモジュール/fun を持つノード) に渡すことができ、その後、誰もが満足します。おそらく、ターゲットノードには上記の名前のモジュールがロードされていますが、バージョンが異なる可能性があります。その場合、MD5 チェックサムが異なる可能性が非常に高いため、適用しようとするとエラー badfun が発生します。
非常に興味深いので、記事全体を読むことをお勧めします。
有効な Erlang 用語を送信できます。ファンを送るときは注意が必要ですが。モジュール内の関数を参照する楽しみは、そのモジュールが動作するターゲット ノードに存在する必要があります。
(first@host)9> rpc:call(second@host, erlang, apply,
[fun io:format/1, ["Hey!~n"]]).
Hey!
ok
(first@host)10> mymodule:func("Hey!~n").
5
(first@host)11> rpc:call(second@host, erlang, apply,
[fun mymodule:func/1, ["Hey!~n"]]).
{badrpc,{'EXIT',{undef,[{mymodule,func,["Hey!~n"]},
{rpc,'-handle_call_call/6-fun-0-',5}]}}}
この例では、両方のノードに存在し、fun としてio
関数を送信するように機能します。io
ただし、mymodule
存在するのは最初のノードのみであり、funundef
は他のノードで呼び出されると例外を生成します。
匿名関数については、送信して期待どおりに動作するようです。
t1@localhost:
(t1@localhost)7> register(shell, self()).
true
(t1@localhost)10> A = me, receive Fun when is_function(Fun) -> Fun(A) end.
hello me you
ok
t2@localhost:
(t2@localhost)11> B = you.
you
(t2@localhost)12> Fn2 = fun (A) -> io:format("hello ~p ~p~n", [A, B]) end.
#Fun<erl_eval.6.54118792>
(t2@localhost)13> {shell, 't1@localhost'} ! Fn2.
riak-core で構築されたアプリにカバレッジ ロジックを追加していますが、匿名関数をメッセージで使用できない場合、収集された結果のマージが難しくなる可能性があります。
riak_kv/src/riak_kv_coverage_filter.erlもチェックしてください
riak_kv がそれを使ってfilter
結果を出しているのかもしれません。