gunnar2k
gunnar2k

Reputation: 195

Wrap elixir module

If you have a module, for instance

defmodule Foo do
    # lots of "unknown" functions
end

How can I create a wrapper-module for that Foo, like:

defmodule Bar do
    # wrap all functions in Foo
end

But in Bar I want to expose all functions in Foo, but additionally I want to add some code in each function, specifically I want to try/catch a specific error that can show up in any Foo.Error exception... I'd like to do this without adding a function for each function in Foo, since that will get repetetive.

Can I do this with macros?

Upvotes: 3

Views: 678

Answers (3)

Hauleth
Hauleth

Reputation: 23556

With magic of metaprogramming everything is possible (however not always this makes sense):

defmodule Bar do
  Code.ensure_compiled(Foo)

  for {func, arity} <- Foo.__info__(:functions) do
    args = Macro.generate_arguments(arity, __MODULE__)

    def unquote(func)(unquote_splicing(args)) do
      Foo.unquote(func)(unquote_splicing(args))
    rescue
      Foo.Error -> handle_error()
    end
  end
end

However this will not work for macros.

Upvotes: 1

Uj Corb
Uj Corb

Reputation: 2159

AFAIU you want to perform some kind of object-oriented programming by replicating the logic of inheritance between classes. But this is not the philosophy of any functional programming language like Elixir as you probably already know.

However, If this is really what you want to do, I found this question that uses metaprogramming and aim at doing something similar to what you are looking for. It looks complicated though.

Edit : After we had some further talk I understand your problem better. If you want to define function without too much repetition then metaprogramming is the way to go ! Here is a simple example on how to define several functions in a module thanks to metaprogramming :

defmodule MyModule do
  Enum.each ~w(method1 method2), fn(method_name) ->
    def unquote(:"#{method_name}")(), do: unquote(method_name)
  end
end

I'd like to do this without adding a function for each function in Foo, since that will get repetetive.

I think that's what I would do, but are you sure it would be that repetitive ?

Also you can also use the Exceptional lib that will help you write less error-handling functions :)

Upvotes: 3

errata
errata

Reputation: 26812

This is a good use of defmacro, but definitely look into defedelegate as well. It lets you add(delegate) named references to functions in other/external modules.

Upvotes: 0

Related Questions