如何在elixir上生成函数?

如何在elixir上生成函数?,elixir,Elixir,我正在尝试执行elixir分布式任务指南,但遇到了以下问题: ** (EXIT from #PID<0.62.0>) an exception was raised: ** (BadFunctionError) expected a function, got: #Function<20.50752066/0 in :erl_eval.expr/5> :erlang.apply/2 然后用:iex--name启动machine2silver@19

我正在尝试执行elixir分布式任务指南,但遇到了以下问题:

** (EXIT from #PID<0.62.0>) an exception was raised:
    ** (BadFunctionError) expected a function, got: #Function<20.50752066/0 in :erl_eval.expr/5>
        :erlang.apply/2
然后用:
iex--name启动
machine2
silver@192.168.0.25--cookie foo
并尝试生成
Hello.world
函数:

Node.spawn\u链接:silver@192.168.0.25“,fn->Hello.world end

在此之后,将显示错误

更多信息: 在机器一号节点上。列表返回silver@192.168.0.25“]

在机器二的
节点上。列表
返回
[:“gold@192.168.0.20“]

epmd-names
on
machine one
返回:

epmd: up and running on port 4369 with data:
name gold at port 37295
epmd: up and running on port 4369 with data:
name gold at port 39738
epmd-names
on
machine two
返回:

epmd: up and running on port 4369 with data:
name gold at port 37295
epmd: up and running on port 4369 with data:
name gold at port 39738

首先,你的例子有一个问题。你说

I start machine one with: iex --name gold@192.168.0.20 --cookie foo and run:

iex(silver@192.168.0.25)1> defmodule Hello do
iex(silver@192.168.0.25)1>   def world, do: IO.puts "hello world"
iex(silver@192.168.0.25)1> end
iex会话将在silver上进行,您稍后将启动该会话

此外,epmd列表不显示silver@192.168.0.25是你写的Hello模块

我在同一台机器上的两个iex会话上尝试了这个,效果很好

以下是您应该采取的步骤:

  • 使用该计算机的名称和IP地址启动第一个iex会话
  • 调出第二个iex部分,其中包含机器的名称和IP地址
  • 在其中一个iex会话上,键入“Node.connect”:name@ipaddress“另一台机器的
  • 在一台机器上定义Hello模块
  • 在另一台机器上执行spawn_链接

  • 最后找到答案:

    您需要保证它们运行的是完全相同的Erlang版本。对于生产,我们通常在一台机器上编译代码,并将其分发到多台机器上,以确保在任何地方都有相同的版本

    如果不能保证相同的版本,则必须避免使用匿名函数,并始终使用命名版本,例如:

    Node.spawn_link :"silver@192.168.0.25", &Hello.world/0
    Node.spawn_link :"silver@192.168.0.25", Hello, :world, []
    

    谢谢,但这不是正确的答案。我问的是在两台不同的机器上运行。是的,我刚刚发现传递命名函数是有效的。但不确定匿名函数为什么没有。谢谢你的信息!这是因为使用一个普通函数不能保证在另一端有相同的代码。i、 e:您在一个节点中实现的Hello.world/0与在另一个节点中实现的不同。如果你喜欢我的答案,请投我一票!我怀疑if与序列化函数的AST有更多的关系。函数被转换为二进制表示形式(使用:erlang.term_to_binary)并通过线路发送到远端。然后远端将其转换回erlang术语(使用:erlang.binary\u to\u term)。不同版本可能存在不兼容,这是有道理的。使用命名函数,您只需传递模块、名称、arity,而不是AST。我发现这是一个有趣的阅读,这解决了我的问题(一台机器上有OTP 21,另一台机器上有OTP 18)