Hi,
I’m trying to create some syntactic sugar through a macro. The basic function should look like the following:
f :name do
data.something + 10
end
The macro will transform the body to an anonymous function. Yes the somewhat undefined data
is intentional, it will be used to capture the argument that will be passed to the function.
I didn’t manage to create a macro that resolves the data
correctly. I found now a solution that works by using the anonymous function of the capture operator. The downside is that I need to capture the argument through &1.something
which does not look nice (note the real code looks more complicated since it uses a compile hook, but the following is working)
defmodule F do
defmacro f(name, options, do: block) do
func = quote do
&(unquote(block))
end
quote do
register(unquote(name), unquote(options), unquote(func))
end
end
def register(name, options, func) do
result = func.(%{something: 10})
IO.puts("#{inspect name}, #{inspect options}, #{inspect func}, #{inspect result}")
end
end
defmodule G do
def run() do
import F
F.f :name, [] do
&1.something-10
end
end
end
And call it with:
import G
G.run
If I convert the capturing operator to an anonymous function it should work just fine. The doc does state:
In other words,
&(&1 * 2)
is equivalent tofn x -> x * 2 end
.
But, whenI change my macro to look like this:
defmacro f(name, options, do: block) do
func = quote do
fn(data) -> unquote(block) end
end
quote do
register(unquote(name), unquote(options), unquote(func))
end
end
I get the error:
warning: variable "data" does not exist and is being expanded to "data()", please use parentheses to remove the ambiguity or change the variable name
lib/f.ex:21: G.run/0
== Compilation error in file lib/f.ex ==
** (CompileError) lib/f.ex:21: undefined function data/0 (expected G to define such a function or for it to be imported, but none are available)
Why is this? Can someone please help me to understand this?