According to the quote docs:
Options
…
…
:bind_quoted
- passes a binding to the macro. Whenever a binding is given,unquote/1
is automatically disabled.
This code produces the expected output:
defmodule My do
defmacro go(name) do
quote bind_quoted: [name: name] do
def unquote(name)() do
unquote(name)
end
end
end
end
defmodule Test do
require My
Enum.each [:hello, :goodbye], &My.go(&1)
end
IO.puts Test.hello
IO.puts Test.goodbye
Output:
~/elixir_programs$ iex macros2.ex
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
hello
goodbye
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
But, according to the quote docs, because a binding was given, unquote()
is disabled, so shouldn’t I be able to remove all the calls to unquote()
? This doesn’t work:
defmodule My do
defmacro go(name) do
quote bind_quoted: [name: name] do
def :"#{name}"() do # line 4
name
end
end
end
end
defmodule Test do
require My
Enum.each [:hello, :goodbye], &My.go(&1)
end
IO.puts Test.hello
IO.puts Test.goodbye
Output:
elixir_programs$ iex macros2.ex
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
** (SyntaxError) macros2.ex:4: syntax error before: '('
(elixir) lib/code.ex:677: Code.require_file/2
And, I’m not even sure why the first example works because I’m using a value name
rather than the key :name
for the keyword list [name: name]
.
Even if I change the code to the following it still doesn’t work:
defmodule My do
defmacro go(name) do
quote bind_quoted: [name: name] do
def hello() do
name
end
end
end
end
defmodule Test do
require My
Enum.each [:hello], &My.go(&1)
end
IO.puts Test.hello
The quote docs make no sense.