Macros 在宏中定义和使用函数
下面这个例子:Macros 在宏中定义和使用函数,macros,elixir,Macros,Elixir,下面这个例子: defmodule Greetify do defmacro __using__(_) do quote do Module.register_attribute __MODULE__, :greet, accumulate: true, persist: false @before_compile Greetify end end defmacro __before_compile__(env) do
defmodule Greetify do
defmacro __using__(_) do
quote do
Module.register_attribute __MODULE__, :greet, accumulate: true,
persist: false
@before_compile Greetify
end
end
defmacro __before_compile__(env) do
greetings = Module.get_attribute(env.module, :greet)
for {name, age} <- greetings do
IO.puts "#{name} is #{age} years old"
end
end
end
defmodule Greetify do
定义宏\uuuuuu使用\uuuu(\uu)do
引述
Module.register\u属性\uuuuu Module\uuuuu,:问候,累计:true,
坚持:错
@在你开始贪婪之前
结束
结束
在编译之前定义宏
问候语=Module.get_属性(env.Module,:问候语)
对于{name,age}嗯,这是可能的。代码的问题在于混合了作用域。Elixir中的宏在编译阶段被扩展。此时此刻没有编译的say_greetings/1
函数(除此之外,不能从defmacro
内部调用defp
,但这可以通过适当的引用来克服。)
要使其工作,您需要在编译之前,在与\u相同的范围内声明说问候语/1
,以使其可用。您不能将其定义为函数(见上文),但解决方法是将其定义为宏。这样,它将在编译过程中进行扩展,所有内容都将正常工作(同时,我怀疑我是否理解这样做的原因。)
总结如下:
defmodule Greetify do
定义宏\uuuuuu使用\uuuu(\uu)do
引述
Module.register\u属性\uuuuu模块\uuuuu,:问候、累积:真、持续:假
@在你开始贪婪之前
结束
结束
说问候语(问候语)做什么
引述
对于{name,age}嗯,这是可能的。代码的问题在于混合了作用域。Elixir中的宏在编译阶段被扩展。此时此刻没有编译的say_greetings/1
函数(除此之外,不能从defmacro
内部调用defp
,但这可以通过适当的引用来克服。)
要使其工作,您需要在编译之前,在与\u相同的范围内声明说问候语/1
,以使其可用。您不能将其定义为函数(见上文),但解决方法是将其定义为宏。这样,它将在编译过程中进行扩展,所有内容都将正常工作(同时,我怀疑我是否理解这样做的原因。)
总结如下:
defmodule Greetify do
定义宏\uuuuuu使用\uuuu(\uu)do
引述
Module.register\u属性\uuuuu模块\uuuuu,:问候、累积:真、持续:假
@在你开始贪婪之前
结束
结束
说问候语(问候语)做什么
引述
对于{name,age}谢谢你的回答,是的,我知道它们是编译的,这就是为什么我认为它可以使用before_compile宏。例如,如果我必须使用几个函数而不仅仅是“say_问候语”,那么它们都必须是一个单独的宏,对吗?为了在未编译宏之前在编译范围内可用,在编译之前将它们扩展到AST inplace,这就是为什么在编译开始之前可以访问它们。老实说,除了将它们放入单独的宏中之外,我无法发明其他解决方案,但我不确定这是否不可能以其他方式实现,但可以像您所说的那样在宏中使用适当的引号调用def?是的,但无法执行尚未编译的函数。您可以声明它,是的,但不能调用。谢谢您的回答,是的,我知道它们是编译的,这就是为什么我认为它可以使用before_compile宏。例如,如果我必须使用几个函数而不仅仅是“say_问候语”,那么它们都必须是一个单独的宏,对吗?为了在未编译宏之前在编译范围内可用,在编译之前将它们扩展到AST inplace,这就是为什么在编译开始之前可以访问它们。老实说,除了将它们放入单独的宏中之外,我无法发明其他解决方案,但我不确定这是否不可能以其他方式实现,但可以像您所说的那样在宏中使用适当的引号调用def?是的,但无法执行尚未编译的函数。你可以申报,可以,但不能打电话。
defmacro __before_compile__(env) do
greetings = Module.get_attribute(env.module, :greet)
say_greetings(greetings)
defp say_greetings(grettings) do
for {name, age} <- greetings do
IO.puts "#{name} is #{age} years old"
end
end
end