Erlang 源代码可以嵌入到 Elixir 代码中吗?如果是这样,如何?

Can Erlang source code be embedded in Elixir code? If so, how?

可以使用代码注入 Elixir 源。eval_string/3。我没有在文档中看到 运行 原始 Erlang 代码的提及:

https://hexdocs.pm/elixir/Code.html#eval_string/3

我来自 Scala 世界,其中 Java 个对象可以使用 Scala 语法调用,并且 Scala 被编译成 Java 并通过拦截编译器输出(直接用 scalac 生成)可见。

我觉得 Elixir 不提供此类互操作功能,也不允许将自定义 Erlang 注入运行时。是这样吗?

您可以使用 Elixir 中的 erlang 标准库模块,如here or here所述。

例如:

def random_integer(upper) do
  :rand.uniform(upper) # rand is an erlang library
end

您还可以将 erlang 包添加到您的 mix.exs 依赖项并在您的项目中使用它们,只要这些包发布在 hex 或 github.

您还可以按照 here 所述在项目中一起使用 erlang 和 elixir 代码。

所以是的,从 elixir 调用 erlang 代码是完全可能的。

反之亦然,更多信息见here

Elixir compiles into BEAM byte code (via Erlang Abstract Format). This means that Elixir code can be called from Erlang and vice versa, without the need to write any bindings.

扩展@zwippie 所写的内容:

所有 远程函数调用(我指的是显式设置 module/alias 的调用函数)的形式为:

<atom with module name>.<function name>(<arguments>)

# Technically it is the same as:
# apply(module, function_name_as_atom, [arguments])

Elixir 中的所有“大写模块名称”都是原子:

is_atom(Foo) == true
Foo == :"Elixir.Foo" # => true

所以从 Elixir 的角度来看,调用 Erlang 函数和 Elixir 函数之间没有区别。它只是作为接收模块传递的不同原子。

因此您可以轻松地从 Elixir 调用 Erlang 模块。这意味着您应该也可以在 Elixir 中轻松编译 Erlang AST:

"rand:uniform(100)"
|> :merl.quote()
|> :erl_eval.expr(#{})

无需任何心理翻译。


此外,您可以毫无问题地在单个 Mix 项目中混合使用 Erlang 和 Elixir 代码。树结构如下:

.
|`- mix.exs
|`- src
|  `- example.erl
 `- lib
   `- example.ex

其中 example.erl 是:

-module(example).

-export([hello/0]).

hello() -> <<"World">>.

example.ex

defmodule Example do
  def print_hello, do: IO.puts(:example.hello())
end

您可以编译项目并运行它

mix run -e "Example.print_hello()"

并且看到 Erlang 模块在同一项目中从 Elixir 代码中成功编译和执行,没有任何问题。

从 elixir 调用 erlang 代码时还需要注意一件事。 erlang 对字符串使用字符列表。当您调用带有字符串的 erlang 函数时,将字符串转换为字符列表并将返回的字符串转换为字符串。

示例:

iex(17)> :string.to_upper "test"
** (FunctionClauseError) no function clause matching in :string.to_upper/1

    The following arguments were given to :string.to_upper/1:

        # 1
        "test"

    (stdlib 3.15.1) string.erl:2231: :string.to_upper/1
iex(17)> "test" |> String.to_charlist() |> :string.to_upper
'TEST'
iex(18)> "test" |> String.to_charlist() |> :string.to_upper |> to_string
"TEST"
iex(19)>