远程节点位于不同的计算机上。
我从本地节点测试:
$ erl -name foobar
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:2:2] [async-threads:10] [kernel-poll:false]
Eshell V6.2 (abort with ^G)
(foobar@debian.localdomain)1> Aliyun='aliyun@localhost2.localdomain'.
'aliyun@localhost2.localdomain'
(foobar@debian.localdomain)2> spawn(Aliyun, fun() -> io:format("hello~n") end).
<6108.86.0>
(foobar@debian.localdomain)3>
=ERROR REPORT==== 4-Jul-2015::21:03:27 ===
Error in process <0.86.0> on node 'aliyun@localhost2.localdomain' with exit value: {{badfun,#Fun<erl_eval.20.90072148>},[{erlang,apply,2,[]}]}
(foobar@debian.localdomain)3> spawn(Aliyun, io, format, ["hello~n"]).
hello
<6108.87.0>
(foobar@debian.localdomain)4> net_adm:ping(Aliyun).
pong
您可以看到spawn(node,module,function,args)
有效,但spawn(node,fun)
没有。
远程节点上的Erlang版本是R15,而本地节点上的版本是R17。是原因吗?因为代码格式不同?我不清楚Erlang如何在将它传递给远程节点时编组有趣的类型。在字节码?
请帮忙!
答案 0 :(得分:9)
正如您收到的错误消息所示,匿名函数在此上下文中基本上被视为在erl_eval
模块中定义。如果在发送节点和接收节点上都有相同版本的erl_eval
,那么一切正常,因为在这种情况下,erl_eval
的两个副本都具有相同的版本和校验和,因此接收节点是正确的能够评估从发送节点传递的匿名函数。但是如果两个节点具有不同的erl_eval
模块,则评估匿名函数将失败。
尝试一个有趣的事情是在R15节点上定义匿名函数,通过term_to_binary/1
将其转换为二进制,将生成的二进制文件发送或复制到17.x节点,将其转换回术语来自binary_to_term/1
,然后将生成的术语作为匿名函数传递给spawn
来电。首先,在R15节点上:
(r15@myhost)1> F = fun() -> io:format("hello~n") end.
(r15@myhost)2> Bin = term_to_binary(F).
<<131,112,0,0,2,179,0,158,45,156,12,16,101,74,154,214,21,
222,196,219,108,205,131,0,0,0,20,0,0,...>>
(r15@myhost)3> file:write_file("/tmp/fun", Bin).
ok
现在将二进制文件读入17.x节点,然后用spawn
调用它回到R15节点:
(r17@myhost)1> {ok, Bin} = file:read_file("/tmp/fun").
{ok,<<131,112,0,0,2,179,0,158,45,156,12,16,101,74,154,
214,21,222,196,219,108,205,131,0,0,0,20,...>>}
(r17@myhost)2> F = binary_to_term(Bin).
#Fun<erl_eval.20.82930912>
(r17@myhost)3> spawn(r15@myhost, F).
hello
<7101.90.0>
正如您所看到的 - 您也应该亲自尝试 - spawn
调用按预期工作,因为匿名函数是在R15节点上创建的,并且它也在那里进行评估。 17.x节点只传递它。