问题
Is it possible to rename an existing Erlang module? I have some code in several Erlang modules that I want to use in an Elixir project (assertion library).
I don't want to convert all the Erlang modules to Elixir as they are complete, but I want to rename them, and possible add additional functions to them. Both modules are simply collections of functions, they don't implement behaviors or do anything unusual.
I want to be able to take an existing Erlang module:
-module(foo_erl).
-export([some_fun/1]).
some_fun(Arg) ->
ok.
And write an Elixir module to extend the Erlang one:
defmodule ExFoo do
somehow_extends_erlang_module :foo_erl
another_fun(arg) do
:ok
end
end
And then be able to use the functions defined in the Erlang module:
iex(1)> ExFoo.some_fun(:arg) #=> :ok
Is this possible in Elixir? If so, how would I go about doing this?
回答1:
In general, we suggest to avoid wrapping Erlang modules. In case you want to wrap many modules in an automatic fashion, velimir's post is right on the spot.
If you have one-off case though, where you definitely want to wrap an Erlang module, I would suggest to simply use defdelegate:
defmodule MyLists do
defdelegate [flatten(list), map(fun, list)], to: :lists
end
回答2:
Here's the first thing that I can suggest. I'm 100% sure that it could be solved in a more elegant way. I'll back to this later since I'm not an Elixir guru yet.
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
来源:https://stackoverflow.com/questions/25694387/elixir-rename-and-wrap-erlang-module