Ho una macro che definisce un modulo come tale.Elixir macros and bind_quotated
defmodule Bar do
def bar do
IO.puts "I am #{inspect __MODULE__}"
end
end
defmodule MacroFun do
defmacro define_module(name) do
quote do
defmodule unquote(name) do
import Bar
def foo do
bar
IO.puts "I am #{inspect __MODULE__}"
end
end
end
end
end
defmodule Runner do
require MacroFun
def run do
MacroFun.define_module Foo
Foo.foo
end
end
Runner.run
L'uscita del funzionamento di questo è:
I am Bar
I am Runner.Foo
che ha un senso; MacroFun.define_module
è stato chiamato in Runner.run
così il modulo è stato definito e quindi annidato sotto il modulo Runner
.
Ma ora se cambio MacroFun.define_module
per utilizzare l'opzione :bind_quoted
:
defmacro define_module(name) do
quote bind_quoted: [name: name] do
defmodule name do
import Bar
def foo do
bar
IO.puts "I am #{inspect __MODULE__}"
end
end
end
end
L'uscita diventa ora:
I am Bar
I am Foo
Perché ??
Wow, che è abbastanza sottile, ma ha un senso. Ricapitolare per essere sicuri di capire: quando viene usato 'bind_quoted', quindi' name' è non quotato _outside_ il corpo ('do'..'end') della citazione. Ma quando 'bind_quoted' non viene usato, quindi' name' è esplicitamente non quotato all'interno della citazione. – cjbottaro
Citando Heisenberg da Breaking Bad: "Hai maledettamente ragione". –