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

Posted

技术标签:

【中文标题】Erlang 消息可以发送哪些类型的消息?【英文标题】:What kind of types can be sent on an Erlang message? 【发布时间】:2011-08-31 22:56:15 【问题描述】:

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

在机器 1 上:

F1 = Fun()-> hey end,

gen_server:call(on_other_machine,F1)

在机器 2 上:

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

有意义吗?

【问题讨论】:

【参考方案1】:

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

[...] 你可能知道,Erlang 发行版 通过发送二进制编码来工作 条款;所以发送一个乐趣也是 基本上是通过使用对其进行编码来完成的 二郎:term_to_binary/1;通过 生成的二进制文件到另一个节点,并且 然后再次使用解码它 erlang:binary_to_term/1.[...] 这很明显 对于大多数数据类型;但它是怎么做的 为函数对象工作?

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

[...]函数的定义没有传递;如果模块在那里,刚好足够的信息在另一个节点上重新创造乐趣。

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

[...] 如果您从不尝试应用该功能,则不会发生任何不好的事情。乐趣可以传递到另一个节点(有问题的模块/乐趣),然后每个人都很开心。 也许目标节点有一个加载了该名称的模块,但可能是不同的版本;然后很可能有不同的 MD5 校验和,如果您尝试应用它,则会收到错误 badfun。

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

【讨论】:

【参考方案2】:

您可以发送任何有效的 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 异常。

【讨论】:

匿名函数呢? 如果你的意思是匿名娱乐,​​它也有同样的问题。 IE。定义它的模块必须存在于远程节点上。【参考方案3】:

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

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 结果,我猜。

【讨论】:

以上是关于Erlang 消息可以发送哪些类型的消息?的主要内容,如果未能解决你的问题,请参考以下文章

Erlang进程发送消息

RabbitMQ消息队列随笔

在 Erlang 中发送/接收消息(并发)

在erlang中向远程节点端口发送消息

用erlang解析ejabberd数据包

Erlang 模块向 shell 程序发送和接收消息