嗯,这是可能的。代码的问题是混合了作用域。Elixir中的宏在编译阶段被扩展。没有已编译的
say_greetings/1
此时的函数(除此之外,不能调用
defp
从内部
defmacro
,但这可能会被适当的引用所克服。)
你需要做的是申报
说\u问候/1
在与相同的范围内
__before_compile__/1
使可用。您不能将其定义为函数(见上文),但解决方法是定义它
作为一个宏
.那样的话
扩展的
在编译过程中,一切都会起作用(同时,我怀疑我是否理解这是为什么。)
总结如下:
defmodule Greetify do
defmacro __using__(_) do
quote do
Module.register_attribute __MODULE__, :greet, accumulate: true, persist: false
@before_compile Greetify
end
end
defmacrop say_greetings(greetings) do
quote do
for {name, age} <- unquote(greetings) do
IO.puts "#{name} is #{age} years old"
end
end
end
defmacro __before_compile__(env) do
greetings = Module.get_attribute(env.module, :greet)
say_greetings(greetings)
end
end
defmodule Test do
use Greetify
@greet {"Jon", 21}
@greet {"Sam", 23}
end