Эликсир переименовать и завернуть в модуль Erlang?

Можно ли переименовать существующий модуль Erlang? У меня есть код в нескольких модулях Erlang, который я хочу использовать в проекте Elixir (библиотека утверждений). Я не хочу конвертировать все модули 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

Это возможно в эликсире? Если так, как бы я поступил так?

2 ответа

Решение

В общем, мы рекомендуем избегать упаковки модулей Erlang. Если вы хотите автоматически обернуть множество модулей, пост Велимира прямо на месте.

Если у вас есть одноразовый случай, где вы определенно хотите обернуть модуль Erlang, я бы предложил просто использовать defdelegate:

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

Вот первое, что я могу предложить. Я на 100% уверен, что это можно решить более элегантным способом. Я вернусь к этому позже, так как я еще не гуру эликсира.

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
Другие вопросы по тегам