简体   繁体   中英

Elixir rename and wrap Erlang module?

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?

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM