I'm learning Elixir and experimenting with the Macro system.
I am trying to make a variable available to a block that will be wrapped with other code by a macro, but I am clearly doing something wrong.
This is my starting point macro, which works. I am ware that there are more idiomatic ways to iterate in Elixir, and I wrote it just as an exercise:
defmodule Loops do
defmacro times(n, [do: block]) do
quote do
Enum.each(1..unquote(n), fn(_) -> unquote(block) end)
end
end
end
import Loops
times 3 do
IO.puts "Hello!"
end
Now, what I want to accomplish is being able to reference the counter from the do block. So, if I give a proper name to the fn argument:
Enum.each(1..unquote(n), fn(_) -> unquote(block) end)
# becomes:
Enum.each(1..unquote(n), fn(counter) -> unquote(block) end)
I would like to be able to do something like this:
times 3 do
IO.puts "Hello! iteration n: #{counter}"
end
This however doesn't work and raises a CompileError because of undefined function counter/0. The error is raised from the do block I passed to the macro invocation, which I find a bit counterintuitive because I thought that the block would be placed in the expanded code when calling unquote().
Am I approaching the problem in the wrong way, or is this simply not possible?