Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros elixir中的宏扩展:如何定义两个宏,其中一个使用另一个?_Macros_Elixir - Fatal编程技术网

Macros elixir中的宏扩展:如何定义两个宏,其中一个使用另一个?

Macros elixir中的宏扩展:如何定义两个宏,其中一个使用另一个?,macros,elixir,Macros,Elixir,我正在用长生不老药试验宏。因此,我将要展示的代码当然应该使用简单的函数来完成,但是。。我在试验 我想定义两个宏(A和B),并使用B来试验宏扩展。 当我使用A时,我得到一个编译错误,表示函数B是未定义的 代码如下: defmodule MyMacros do defmacro print_expr(expr) do quote do IO.puts(unquote(expr)) end end defmacro print_hashes_around(ex

我正在用长生不老药试验宏。因此,我将要展示的代码当然应该使用简单的函数来完成,但是。。我在试验

我想定义两个宏(A和B),并使用B来试验宏扩展。 当我使用A时,我得到一个编译错误,表示函数B是未定义的

代码如下:

defmodule MyMacros do
  defmacro print_expr(expr) do
    quote do
      IO.puts(unquote(expr))
    end
  end

  defmacro print_hashes_around(expr) do
    quote do
      IO.puts "###"
      print_expr(unquote(expr))
      IO.puts "###"
    end
  end
end

defmodule MyModule do
  require MyMacros

  def my_print(expr) do
    MyMacros.print_hashes_around(expr)
  end
end

MyModule.my_print("hello world")
下面是编译错误:

macro_test.exs:17: warning: redefining module MyModule
** (CompileError) macro_test.exs:21: function print_expr/1 undefined
(stdlib) lists.erl:1336: :lists.foreach/2
macro_test.exs:17: (file)
(elixir) lib/code.ex:307: Code.require_file/2
我(错误地)理解事物的方式:

  • 通过要求使用MyMacros,模块MyModule应该知道这两个宏的存在。因此,我应该能够使用任何宏
  • 在MyModule中展开print_hash_around时,编译器应该会发现print_expr也是一个宏。因此,应该进行另一次扩展
  • 似乎发生的是第二次扩张没有发生。因此,编译器会查找不存在的函数定义
  • 我说得对吗

    正如slack中所建议的,在
    print\u expr
    前面加上
    MyMacros。
    修复了它。我还是不明白为什么
    MyModule
    需要
    MyMacros
    ,因此这两个宏都应该是已知的并且可以扩展的。。。当我查看
    的定义时,除非
    ,否则它使用
    if
    ,而不是
    Kernel.if

    通过要求使用MyMacros,模块MyModule应该知道这两个宏的存在。因此,我应该能够使用任何宏

    误解就在这里
    require
    仅使模块可供编译器使用,而不导入模块函数。如果您使用
    import MyModule
    ,那么它就可以工作了

    但是,最好通过在模块名称前加前缀来解决此问题,因为这样可以允许使用代码的开发人员显式使用宏(使用
    require
    )或导入宏

    另一种选择是避免像这样的多个宏调用:

    defmodule MyMacros do
      defmacro print_expr(expr) do
        quoted_print_expr(expr)
      end
    
      defmacro print_hashes_around(expr) do
        quote do
          IO.puts "###"
          unquote(quoted_print_expr(expr))
          IO.puts "###"
        end
      end
    
      defp quoted_print_expr(expr) do
        quote do
          IO.puts(unquote(expr))
        end
      end
    end
    

    谢谢José,能从语言创造者那里得到答案真是太棒了!