1

With elixir's __using__ macro and with the aid of __on_definition__ I can keep track of all methods in a module. What I would like to do is replace all methods in a module with some other implementation. Now it's fairly trivial to create the new methods I want but I also want to remove the existing methods.

Additionally to this, is there a way to apply a macro to several modules without explicitly adding the use XXX to each module. In otherwords if I have a folder structure:

  • foo/
    • bar/
      • module1.ex
      • module2.ex

Could I dynamically apply the using macro to everything in ./foo/bar/.

To simplify my problem, imagine that for all methods in all modules in the foo/bar/ folder I want to change there implementation so that they will first run IO.inspect "called before method", aka some kind of before method aop.

1 Answer 1

2

def is just a macro from Kernel. So you could exclude it with import Kernel, except: [def: 2] and then create you def. Here is something that almost works, except for the return value.

defmodule Def do
  import Kernel, except: [def: 2]
  defmacro __using__(_) do
    quote do
      import Kernel, except: [def: 2]
    end
  end

  defmacro def(call, expr) do
    # caller = __CALLER__
    # IO.inspect call
    # IO.inspect expr

    # import Kernel
    quote do
      Kernel.def unquote(call) do
        IO.puts "do something first"
        unquote(expr)
      end
    end
  end
end

defmodule Special do
  use Def
  import Def

  def test(one, two) do
    IO.puts "one: #{inspect one}, two: #{inspect two}"
  end
end

Running in iex

Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Special.test 1, 2
do something first
one: 1, two: 2
[do: :ok]
iex(2)>

I left some print statement at the top of the custom def macro. You can use this to examine the AST of the inputs to the new def macro.

You can find more information in the Kernel source code.

I have not thought of an idea to automatically apply the use to multiple modules at once. I'm come back and update this if I think of anything.

Sign up to request clarification or add additional context in comments.

1 Comment

Hey Steve, thanks for the reply and I know that I can redefine def. What I was really asking is whether it was possible to not have to explicitly add the usings. Maybe its easier if I just say given a directory can I hook into the compiler to change ALL modules in the directory without explicitly calling using or any macros in the module code itself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.