So in the docs for defmacro
in Elixir we have (I put in a hello
method for example purposes):
defmodule MyLogic do
defmacro unless(expr, opts) do
quote do
if !unquote(expr), unquote(opts)
end
end
def hello, do: "hello"
end
Then if I try to introspect on available functions, only hello/0 shows.
iex(3)> MyLogic.__info__(:functions)
[hello: 0]
But calling:
MyLogic.unless false do
IO.puts("It works")
end
does invoke the macro.
My understanding is that the macro is expanded into final AST form and there is no trace of it once it is compiled. What I'm finding a bit confusing is that it seems you can invoke unless
like a function but there's no trace of it in the introspection .__info__(:functions)
.
1) I think you cannot introspect on macro definitions post-compilation because there's no trace of it after compilation, but in building a mental model of "unless" after it is expanded, how should I represent it in my mind? Should I just look at it as "MyLogic" now has this atom name unless
that invokes the result of the if expression if !unquote(expr), unquote(opts)
.
2) And how does Elixir know then that unless
is a shortcut to the fully expanded macro code?