Elixir重命名并包装Erlang模块?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elixir重命名并包装Erlang模块?相关的知识,希望对你有一定的参考价值。

是否可以重命名现有的Erlang模块?我想在Elixir项目(断言库)中使用的几个Erlang模块中有一些代码。

我不想将所有Erlang模块转换为Elixir,因为它们已完成,但我想重命名它们,并可能为它们添加其他功能。这两个模块都只是函数集合,它们不实现行为或做任何不寻常的事情。

我希望能够使用现有的Erlang模块:

-module(foo_erl).

-export([some_fun/1]).

some_fun(Arg) ->
  ok.

并编写一个Elixir模块来扩展Erlang:

defmodule ExFoo do
   somehow_extends_erlang_module :foo_erl

   another_fun(arg) do
     :ok
   end
end

然后能够使用Erlang模块中定义的函数:

iex(1)> ExFoo.some_fun(:arg) #=> :ok

Elixir有可能吗?如果是这样,我该怎么做呢?

答案

一般来说,我们建议避免包装Erlang模块。如果你想以自动方式包装许多模块,velimir的帖子就在现场。

如果你有一次性的情况,你肯定想要包装一个Erlang模块,我建议只使用defdelegate

defmodule MyLists do
  defdelegate [flatten(list), map(fun, list)], to: :lists
end
另一答案

这是我可以提出的第一件事。我百分百肯定它可以以更优雅的方式解决。我稍后会回到这里,因为我还不是Elixir的大师。

defmodule Wrapper do
  defmacro __using__(module) do
    exports = module.module_info[:exports] -- [module_info: 0, module_info: 1]
    for {func_name, arity} <- exports do
      args = make_args(arity)
      quote do
        def unquote(func_name)(unquote_splicing(args)) do
          unquote(module).unquote(func_name)(unquote_splicing(args))
        end
      end
    end
  end

  defp make_args(0), do: []
  defp make_args(arity) do
    Enum.map 1..arity, &(Macro.var :"arg#{&1}", __MODULE__)
  end
end

defmodule WrapperTest do
  use ExUnit.Case, async: true

  use Wrapper, :lists

  test "max function works properly" do
    assert (max [1, 2]) == 2
  end
end

以上是关于Elixir重命名并包装Erlang模块?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Erlang 的 Elixir 模块失败

Elixir Enum vs Erlang列表

如何在Elixir或Erlang中在运行时动态创建和加载模块?

在 Elixir 或 Erlang 中,如何在运行时动态创建和加载模块?

使用 Elixir 和 Erlang ssl 模块获取 SSL 证书

如何检查 ETS Erlang/Elixir 中是不是存在命名表