扩建后的反思宏观灵药以及它如何定义

问题描述 投票:0回答:2

因此,在药剂的文档的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是一个快捷方式到完全展开宏代码?

elixir
2个回答
2
投票

根据the documentation,所述:functions原子用于检索仅一个模块的功能。

如果你想获得宏相反,你应该提供原子:macros__info__/1代替。

既然你不能有一个宏观和共享两个相同的名称和参数数量的函数,这很容易让药剂来区分两者。


0
投票

@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")

unquotequote 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中得到的光束执行代码(编译通过后。)宏没有。

© www.soinside.com 2019 - 2024. All rights reserved.