Reputation: 34099
I have following code snippet:
defmodule Play do
defmacro mobile(expr) do
IO.puts "I will compile"
quote do
IO.puts "#{inspect unquote(expr)}"
unquote(expr)
end
end
end
defmodule Run do
import Play
def run do
IO.puts "Execute macro"
mobile(2+2)
end
end
When I compile this file, I've got following output
iex(46)> c "playground.exs"
I will compile
[Run, Play]
As you can see, elixir compiles macro but quote block is untouched. So when I run following code snippet:
iex(47)> import Run
nil
iex(48)> Run.run
Execute macro
4
4
The quote expression in macro is going to executed, as expected.
Now I remove the run module
defmodule Play do
defmacro mobile(expr) do
IO.puts "I will compile"
quote do
IO.puts "#{inspect unquote(expr)}"
unquote(expr)
end
end
end
Compiles the file
iex(49)> c "playground.exs"
playground.exs:1: warning: redefining module Play
[Play]
Where is here the text I will compile
?
And later, import the module
iex(50)> import Play
nil
execute it
iex(51)> Play.mobile 2 + 2
I will compile
4
4
And voila the text appears.
What is the difference, when I import a macro into a module and import into shell? Why I did not get the text I will compile
one the second example?
Upvotes: 1
Views: 261
Reputation: 13837
The macro isn't executed when the module defining it (Play
) is compiled. It's executed when a module that calls it is compiled. You'll only see "I will compile" when the macro is executed, so it should probably say "I will execute."
In your first example, the macro is executed when the Run
module is compiled.
In your second example, the macro is executed when the repl compiles the line of code you gave it.
You could further verify this for yourself if you split your Run
module out into its own file. Compile Play
and then compile Run
and see when you get the "I will compile" message.
Upvotes: 2