可以在erlang消息上发送什么类型的类型?

时间:2011-05-24 13:29:30

标签: erlang otp gen-server

主要是我想知道我是否可以在分布式erlang设置中的消息中发送函数。

机器1上的

F1 = Fun()-> hey end,

gen_server:call(on_other_machine,F1)
机器2上的

handler_call(Function,From,State) ->
{reply,Function(),State)

有意义吗?

3 个答案:

答案 0 :(得分:8)

Here是一篇关于“将趣味传递给其他Erlang节点”的有趣文章。简要地恢复:

  

[...]您可能知道,Erlang分发   通过发送二进制编码来工作   条款;所以发送一个有趣的也是   基本上通过使用编码来完成   二郎:term_to_binary / 1;通过   结果二进制到另一个节点,和   然后再使用它解码它   二郎:binary_to_term / 1 [...]   这很明显   对于大多数数据类型;但是怎么做   为功能对象工作?

     

编码乐趣时,编码的是什么   只是对函数的引用,   不是功能实现。   [...]

     

[...]函数的定义未传递;如果模块在那里,只需要足够的信息来重建其他节点的乐趣。

     

[...]如果尚未加载包含乐趣的模块,并且目标节点以交互模式运行;然后使用常规模块加载机制(包含在模块error_handler中)尝试加载模块;然后它试图查看所述模块中是否有与给定id相关的乐趣。但是,当您尝试应用该函数时,这种情况只会延迟发生。

     

[...]如果你从未尝试过应用这个功能,那么一切都不会发生。乐趣可以传递到另一个节点(有问题的模块/乐趣),然后每个人都很高兴。   也许目标节点有一个加载了所述名称的模块,但也许是一个不同的版本;那么很可能会有一个不同的MD5校验和,如果你试图应用它就会得到错误badfun。

我建议你阅读整篇文章,因为它非常有趣。

答案 1 :(得分:6)

您可以发送任何有效的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}]}}}

在此示例中,io存在于两个节点上,它可以将io中的函数作为一种乐趣发送。但是,mymodule仅存在于第一个节点上,并且当在另一个节点上调用时,fun会生成undef异常。

答案 2 :(得分:4)

对于匿名函数,它们似乎可以按预期发送和工作。

T1 @本地:

(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 @本地:

(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上的应用程序添加覆盖逻辑,如果无法在消息中使用匿名函数,则收集的结果的 merge 会很棘手。

另请查看riak_kv/src/riak_kv_coverage_filter.erl

riak_kv可能会将它用于filter结果,我猜。