Erlang消息可以发送哪些类型?

pb3s4cty  于 2022-12-08  发布在  Erlang
关注(0)|答案(3)|浏览(261)

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

    • 在计算机1上:**
F1 = Fun()-> hey end,

gen_server:call(on_other_machine,F1)
    • 在计算机2上:**
handler_call(Function,From,State) ->
{reply,Function(),State)

这有道理吗?

5jvtdoz2

5jvtdoz21#

Here是一篇关于"将乐趣传递给其他Erlang节点"的有趣文章。
[...]您可能知道,Erlang分发通过发送术语的二进制编码来工作;因此发送fun本质上也是通过使用erlang:term_to_binary/1对其进行编码来完成的;将得到的二进制文件传递给另一个节点,然后使用erlang:binary_to_term/1再次对其进行解码。[...]这对于大多数数据类型来说是非常明显的;但它如何处理函数对象呢?
当你对一个fun进行编码时,编码的只是对函数的引用,而不是函数的实现。[...]
[...]函数的定义未被传递;如果该模块在另一个节点上,则该信息刚好足够在该另一个节点上重新创建FUN。
[...]如果包含fun的模块尚未加载,并且目标节点正在交互模式下运行;则尝试使用常规模块加载机制(包含在模块error_handler中)来加载该模块;然后它会尝试查看在该模块中是否有一个具有给定id的函数可用。然而,这只会在您尝试应用该函数时发生。
[...]如果你从来没有尝试过应用这个函数,那么就不会有什么不好的事情发生。这个函数可以被传递到另一个节点(它有这个模块/函数),然后每个人都很高兴。也许目标节点有一个模块加载了这个名字,但是可能是不同的版本;这样很可能会有不同的MD5校验和,如果尝试应用它,则会出现错误badfun。
我建议你读整篇文章,因为它非常有趣。

dm7nw8vv

dm7nw8vv2#

你可以发送任何有效的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中的函数作为fun发送。但是,mymodule只存在于第一个节点上,当在另一个节点上调用fun时,它会生成undef异常。

f1tvaqid

f1tvaqid3#

至于匿名函数,它们似乎可以被发送并按预期工作。
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结果。

相关问题