【问题标题】:About invoke macro inside module关于调用模块内的宏
【发布时间】:2018-08-02 21:57:54
【问题描述】:
defmodule DemoMacro do
  defmacro i_am_macro do
    quote do
      # ……
    end
  end

  i_am_macro # (CompileError) example.exs:10: undefined function i_am_macro/0
end

但是从其他模块导入,可以成功调用:

defmodule SecondModule do
  require DemoMacro
  DemoMacro.i_am_macro
end

我应该怎么做才能编译第一段代码?

【问题讨论】:

    标签: elixir


    【解决方案1】:

    您正在从模块主体调用宏,意思是在编译阶段。在编译阶段,这个模块内容显然还不能访问,因为模块没有被编译。

    将宏移动到函数中:

    defmodule DemoMacro do
      defmacro i_am_macro do
        quote do
          IO.puts "Inside a macro"
        end
      end
    
      def test_macro(), do: i_am_macro()
    end
    
    DemoMacro.test_macro()
    #⇒ "Inside a macro"
    

    宏内容是在每次宏调用时就地注入的 AST。在编译阶段,您可能会使用已编译 Elixir 代码。理解编译阶段和运行时之间的区别需要心理上的转变,主要是因为在这两个阶段我们使用相同的 Elixir 语法。但问题是 Elixir 作为一种编译语言,除非将其编译成 BEAM,否则无法使用代码。


    您还可以在编译阶段,在模块 BEAM 可用(已编译)后立即在 @after_compile 回调中使用您的宏:

    defmodule DemoMacro do
      defmacro i_am_macro do
        quote do
          IO.puts "Inside a macro"
        end
      end
    
      @after_compile __MODULE__
    
      def __after_compile__(env, _bytecode) do
        i_am_macro()
      end
    end
    #⇒ immediately prints "Inside a macro"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多