I’m trying to implement a conceptual test with the following macro. I want to be able to pass an action argument which will call a function of the same name in another module with the msg macro argument as the callback function’s argument. This is the same design as the instrument/3 macro in Phoenix.Endpoint.Instrument. But I’m getting an error when I try to compile it.
Can anyone help me understand why?
Error:
warning: variable "action" does not exist and is being expanded to "action()", please use parentheses to remove the ambiguity or change the variable name
macro.ex:11
== Compilation error on file macro.ex ==
** (CompileError) macro.ex:11: undefined function action/0
(elixir) expanding macro: Kernel.def/2
macro.ex:10: MacroTest (module)
(elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
** (exit) shutdown: 1
(elixir) lib/kernel/parallel_compiler.ex:291: Kernel.ParallelCompiler.handle_failure/3
(elixir) lib/kernel/parallel_compiler.ex:247: Kernel.ParallelCompiler.wait_for_messages/1
(elixir) lib/kernel/parallel_compiler.ex:62: Kernel.ParallelCompiler.spawn_compilers/3
(iex) lib/iex/helpers.ex:170: IEx.Helpers.c/2
The code:
defmodule MacroTest do
defmacro my_macro(action, msg) do
sender = " from #{__MODULE__}"
quote do
unquote(__MODULE__).my_fun(unquote(action), unquote(msg), unquote(sender))
end
end
def my_fun(action, var!(msg), var!(sender)) do
unquote(MacroTest.run_action(action))
end
def run_action(action) do
quote do
MyOtherModule.unquote(action)(var!(msg), var!(sender))
end
end
end
defmodule MyOtherModule do
def sender(msg, sender) do
send self(), msg <> sender
end
def printer(msg, sender) do
IO.puts msg <> sender
end
end


















