Макросы получают AST и возвращают AST . Возвращенный AST вводится в место, откуда был вызван этот макрос, вместо вызова макроса. Для возврата AST используется Kernel.quote/2
. Тем не менее, ниже будет работать:
defmodule ExBs.Component do
defmacro defcomp(name, opts) do
quote do
func = Keyword.get(unquote(opts), :func, fn _ -> "" end)
IO.inspect(func)
func.("foo")
end
end
end
defmodule ExBs.Foo do
import ExBs.Component
defcomp(:foo,
func: &IO.inspect/1
)
end
#⇒ #Function<0.48519526 in file:iex>
"foo"
Обратите внимание, что функция была выполнена на этапе компиляции , а именно во время раскрытия макроса. Тем не менее, полученный луч не имеет следов этой функции.
Я сомневаюсь, что это именно то, что вы на самом деле хотели, но не зная, чего вы пытаетесь достичь, невозможно предложить что-то более ценное. В любом случае, теперь код копируется и работает так, как задумано.
Дикая догадка: если вы захотите объявить функцию :foo
wrapping func
, то будет сделано следующее:
defmodule ExBs.Component do
defmacro defcomp(name, opts) do
func = Keyword.get(opts, :func)
quote do
def unquote(name)(), do: unquote(func).("foo")
end
end
end
defmodule ExBs.Foo do
import ExBs.Component
defcomp(:foo,
func: &IO.inspect/1
)
end
ExBs.Foo.foo
#⇒ "foo"