因此,在药剂的文档的defmacro
我们(我把例如目的hello
方法):
defmodule MyLogic do
defmacro unless(expr, opts) do
quote do
if !unquote(expr), unquote(opts)
end
end
def hello, do: "hello"
end
然后,如果我尝试反思上可用的功能,只能你好/ 0节目。
iex(3)> MyLogic.__info__(:functions)
[hello: 0]
但调用:
MyLogic.unless false do
IO.puts("It works")
end
并调用宏。
我的理解是,宏被扩展到最终的AST形式并没有它的踪影,一旦它被编译。什么我发现有点混乱的是,它似乎可以调用unless
的功能等,但有在反省.__info__(:functions)
没有它的踪影。
1)我认为你不能在宏定义反思编译后,因为编译后有没有它的踪影,但在建设的心智模式“除非”它展开后,应该怎么代表它在我的脑海?我应该把它看作是“MyLogic”现在有这个原子名unless
调用的,如果表达if !unquote(expr), unquote(opts)
的结果。
2)又如何药剂知道那么unless
是一个快捷方式到完全展开宏代码?
根据the documentation,所述:functions
原子用于检索仅一个模块的功能。
如果你想获得宏相反,你应该提供原子:macros
到__info__/1
代替。
既然你不能有一个宏观和共享两个相同的名称和参数数量的函数,这很容易让药剂来区分两者。
@TGO已经介绍了为什么__info__(:functions)
不显示unless
一个完美的答案;我仍然认为还需要一些澄清。
我的理解是,宏被扩展到最终的AST形式并没有它的踪影,一旦它被编译。
那的确是非常真实的。事情是药剂正在编制一切执行之前,并通过无平均通话MyLogic.unless ...
你写/调用宏。会发生什么,你指示药剂注入代码的编译过程中MyLogic.unless
返回到您的代码,而不是MyLogic.unless
的AST。有没有在最后的光束宏的痕迹。
我应该怎么代表它在我的脑海?
MyLogic.unless false, do: IO.puts("It works")
恰好扩展到:
if !false, do: IO.puts("It works")
unquote
是quote do
号召下宏观声明必要存在,因为宏确实收到报价表达式作为参数。您可以尝试IO.inspect/2
参数宏调用里面,quote do
之外:
defmacro unless(expr, opts) do
IO.inspect({expr, opts}, label: "compilation time!")
quote, do: if !unquote(expr), unquote(opts)
end
如何药剂知道那么
unless
是一个快捷方式到完全展开宏代码?
有灵药如何维护上这个保证金是太小,无法包含编译阶段内部信息一个真正了不起的解释。在一般情况下,药剂什么也不知道。你应该明确区分编译时和运行时环境。你说的是执行。这一切都被编译后会与您的自定义MyLogic.unless/1
不存在了,由AST取代注射。
药剂不能执行不能编译代码,它不是一种脚本语言。不要被愚弄REPL:引擎盖下iex
有效编译一切你真正执行前“执行”那里。
在药剂宏实际上是一个功能(从您的意见,以另一种答案)
这绝不是正确的。功能确实存在为得到由ErlangVM中得到的光束执行代码(编译通过后。)宏没有。