Эликсир переименовать и завернуть в модуль 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