Erlang源代码可以嵌入Elixir代码吗?如果可以,如何嵌入?

y1aodyip  于 2022-12-08  发布在  Erlang
关注(0)|答案(3)|浏览(216)

Elixir源代码可以使用Code.eval_string/3注入。我没有看到在文档中提到运行原始Erlang代码:
https://hexdocs.pm/elixir/Code.html#eval_string/3
我来自一个Scala世界,在这个世界中,Java对象可以使用Scala语法调用,Scala被编译成Java,并且通过拦截编译器输出(直接使用scalac生成)可见。
我感觉Elixir没有提供这样的互操作特性,也不允许将自定义Erlang注入运行时。是这样吗?

evrscar2

evrscar21#

You can use the erlang standard library modules from Elixir, as described here or here.
For example:

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

You can also add erlang packages to your mix.exs dependencies and use them in your project, as long as these packages are published on hex or on github.
You can also use erlang and elixir code together in a project as described here .
So yeah, it's perfectly possible to call erlang code from elixir.
Vice-versa is also possible, see here for more information:
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.

3yhwsihp

3yhwsihp2#

Expanding what @zwippie have written:

All remote function calls (by that I mean calling function with explicitly set module/alias) are in form of:

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

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

And all "upper case module names" in Elixir are just atoms:

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

So from Elixir viewpoint there is no difference between calling Erlang functions and Elixir functions. It is just different atom passed as the receiving module.
So you can easily call Erlang modules from Elixir. That mean that without much of the hassle you should be able to compile Erlang AST from within Elixir as well:

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

No need for any mental translation.
Additionally you can without any problems mix Erlang and Elixir code in single Mix project. With tree structure like:

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

Where example.erl is:

-module(example).

-export([hello/0]).

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

And example.ex :

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

You can compile project and run it with

mix run -e "Example.print_hello()"

And see that Erlang module was successfully compiled and executed from within Elixir code in the same project without problems.

prdp8dxp

prdp8dxp3#

当从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)>

相关问题