Erlang 源代码可以嵌入到 Elixir 代码中吗?如果是这样,怎么做?
Posted
技术标签:
【中文标题】Erlang 源代码可以嵌入到 Elixir 代码中吗?如果是这样,怎么做?【英文标题】:Can Erlang source code be embedded in Elixir code? If so, how? 【发布时间】:2021-11-08 22:32:18 【问题描述】:Elixir 源可以使用 Code.eval_string/3 注入。我没有看到文档中提到运行原始 Erlang 代码:
https://hexdocs.pm/elixir/Code.html#eval_string/3
我来自 Scala 世界,其中 Java 对象可以使用 Scala 语法调用,Scala 被编译成 Java 并通过拦截编译器输出(直接使用 scalac 生成)可见。
我感觉 Elixir 不提供这样的互操作功能,也不允许将自定义 Erlang 注入运行时。是这样吗?
【问题讨论】:
【参考方案1】:从 elixir 调用 erlang 代码时需要注意的另一件事。 erlang 使用字符列表作为字符串。当你调用一个接受字符串的 erlang 函数时,将字符串转换为 charlist 并将返回的字符串转换为字符串。
例子:
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)>
【讨论】:
感谢您的提示。作为参考,本文档描述了字符串和字符列表之间的区别:elixirschool.com/en/lessons/basics/strings【参考方案2】:扩展@zwippie 所写的内容:
所有远程函数调用(我的意思是调用具有显式设置模块/别名的函数)的形式为:
<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 代码中成功编译和执行,没有问题。
【讨论】:
非常好,非常感谢您提供的示例。【参考方案3】:您可以使用 Elixir 的 erlang 标准库模块,如 here 或 here 所述。
例如:
def random_integer(upper) do
:rand.uniform(upper) # rand is an erlang library
end
您也可以将 erlang 包添加到您的 mix.exs
依赖项中并在您的项目中使用它们,只要这些包发布在 hex
或 github 上即可。
您还可以在项目中同时使用 erlang 和 elixir 代码,如 here 所述。
所以是的,完全可以从 elixir 中调用 erlang 代码。
反之亦然,更多信息请参阅here:
Elixir 编译成 BEAM 字节码(通过 Erlang 抽象格式)。这 意味着可以从 Erlang 调用 Elixir 代码,反之亦然, 无需编写任何绑定。
【讨论】:
另外,如原始问题中所问,Code.eval_string/3
: Code.eval_string(":rand.uniform(100)") #⇒ 38, []
。
优秀。感谢您指向我的文档。
接受是因为参考了文档,但也请参阅@Hauleth 的答案,其中有很好的例子。以上是关于Erlang 源代码可以嵌入到 Elixir 代码中吗?如果是这样,怎么做?的主要内容,如果未能解决你的问题,请参考以下文章