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

发布于 2024-11-09 13:38:47 字数 323 浏览 0 评论 0原文

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

在机器 1 上:

F1 = Fun()-> hey end,

gen_server:call(on_other_machine,F1)

在机器 2 上:

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

这有意义吗?

Mainly I want to know if I can send a function in a message in a distributed Erlang setup.

On Machine 1:

F1 = Fun()-> hey end,

gen_server:call(on_other_machine,F1)

On Machine 2:

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

Does it make sense?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自找没趣 2024-11-16 13:38:47

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

[...] 如您所知,Erlang 发行版
通过发送二进制编码来工作
条款;所以发送一个有趣的也是
本质上是通过使用编码来完成的
erlang:term_to_binary/1;通过
将生成的二进制文件发送到另一个节点,以及
然后使用再次解码
erlang:binary_to_term/1.[...]
这是很明显的
对于大多数数据类型;但怎么办
适用于函数对象?

当你编码一个有趣的东西时,编码的是什么
只是对函数的引用,
不是函数的实现。
[...]

[...]函数的定义没有被传递;如果模块存在,那么信息就足以在其他节点重新创造乐趣。

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

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

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

Here's an interesting article about "passing fun's to other Erlang nodes". To resume it briefly:

[...] As you might know, Erlang distribution
works by sending the binary encoding
of terms; and so sending a fun is also
essentially done by encoding it using
erlang:term_to_binary/1; passing the
resulting binary to another node, and
then decoding it again using
erlang:binary_to_term/1.[...]
This is pretty obvious
for most data types; but how does it
work for function objects?

When you encode a fun, what is encoded
is just a reference to the function,
not the function implementation.
[...]

[...]the definition of the function is not passed along; just exactly enough information to recreate the fun at an other node if the module is there.

[...] If the module containing the fun has not yet been loaded, and the target node is running in interactive mode; then the module is attempted loaded using the regular module loading mechanism (contained in the module error_handler); and then it tries to see if a fun with the given id is available in said module. However, this only happens lazily when you try to apply the function.

[...] If you never attempt to apply the function, then nothing bad happens. The fun can be passed to another node (which has the module/fun in question) and then everybody is happy.
Maybe the target node has a module loaded of said name, but perhaps in a different version; which would then be very likely to have a different MD5 checksum, then you get the error badfun if you try to apply it.

I would suggest you to read the whole article, cause it's extremely interesting.

陌路黄昏 2024-11-16 13:38:47

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

You can send any valid Erlang term. Although you have to be careful when sending funs. Any fun referencing a function inside a module needs that module to exist on the target node to work:

(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}]}}}

In this example, io exists on both nodes and it works to send a function from io as a fun. However, mymodule exists only on the first node and the fun generates an undef exception when called on the other node.

野稚 2024-11-16 13:38:47

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

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 可能会使用它<我猜,代码>过滤结果。

As for anonymous functions, it seems they can be sent and work as expected.

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.

I am adding coverage logic to an app built on riak-core, and the merge of results gathered can be tricky if anonymous functions cannot be used in messages.

Also check out riak_kv/src/riak_kv_coverage_filter.erl

riak_kv might be using it to filter result, I guess.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文