Reputation: 7725
This is common elixir:
defmodule Fizz do
defmacro asdf, do: IO.puts("asdf")
end
defmodule Buzz do
require Fizz
Fizz.asdf
end
However, although you can reference macros in the same context like:
defmodule Fizz do
# ...
defmacro asdf_qwer, do: asdf && IO.puts("qwer")
end
... you can't reference macros in the body of the same module that defined them:
defmodule Fizz do
defmacro asdf, do: IO.puts("asdf")
asdf
end
This raises undefined function asdf/0
.
Is there a workaround for this "problem"? Sometimes I may want to use macros to remove some boilerplate from the module I'm working on, and that macro's functionality may be specific enough not to put it in another module.
Upvotes: 7
Views: 2543
Reputation:
The reason that we're getting undefined function
errors here is because at compile time, the asdf
macro does not yet exist.
So we need to notify the compiler that an extra step is required just before compilation is finished.
One option is the @after_compile module callback attribute which lets you invoke some code just after compilation in order to perform a final bit of code generation.
For example:
defmodule M do
@after_compile __MODULE__
def __after_compile__(env, _bytecode) do
IO.inspect env
end
end
Another option is to put your macros in a Fizz.Macros
module.
Upvotes: 1