elixir是否从shell调用编译宏

时间:2016-04-09 20:59:44

标签: elixir

我有以下代码段:

defmodule Play do

  defmacro mobile(expr) do

    IO.puts "I will compile"

    quote do
      IO.puts "#{inspect unquote(expr)}"
      unquote(expr)
    end

  end

end

defmodule Run do
  import Play

  def run do
    IO.puts "Execute macro"
    mobile(2+2)
  end
end

当我编译这个文件时,我有以下输出

iex(46)> c "playground.exs"
I will compile
[Run, Play]

正如你所看到的,elixir编译宏但引用块是不受影响的。 所以,当我运行以下代码片段时:

iex(47)> import Run
nil
iex(48)> Run.run
Execute macro
4
4

宏中的引用表达式将按预期执行。

现在我删除了运行模块

defmodule Play do

  defmacro mobile(expr) do

    IO.puts "I will compile"

    quote do
      IO.puts "#{inspect unquote(expr)}"
      unquote(expr)
    end

  end

end

编译文件

iex(49)> c "playground.exs"
playground.exs:1: warning: redefining module Play
[Play]

这里的文字I will compile

在哪里

之后,导入模块

iex(50)> import Play
nil

执行它

iex(51)> Play.mobile 2 + 2
I will compile
4
4

瞧,文字出现了。

当我将宏导入模块并导入shell时有什么区别?为什么我没有将文本I will compile作为第二个例子?

1 个答案:

答案 0 :(得分:2)

编译定义它的模块(Play)时,不执行宏。它是在编译调用它的模块时执行的。你只会看到"我会编译"当宏被执行时,它应该说"我将执行。"

在第一个示例中,在编译Run模块时执行宏。

在第二个示例中,当repl编译您提供的代码行时,将执行宏。

如果将Run模块拆分为自己的文件,则可以自行进一步验证。编译Play然后编译Run,看看你什么时候得到"我将编译"消息。