lix剂中的宏扩展:如何使用另一个定义两个宏? [英] Macro expansion in elixir: how to define 2 macros with one using the other?

查看:79
本文介绍了lix剂中的宏扩展:如何使用另一个定义两个宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与宏在酏剂试验.因此,我将要显示的代码当然应该使用简单的函数完成,但是..我正在尝试!

I am experimenting with Macros in elixir. Therefore, the code I'm about to show should certainly be done with simple functions but.. I'm experimenting !

我想定义2个宏(A和B),并让A使用B进行宏扩展实验. 当我使用A,I得到一个编译错误说,在功能 B是的未定义

I want to define 2 macros (A and B) and make A use B to experiment with macro expansion. When I use A, I get a compile error saying that the function B is undefined.

下面是代码:

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

这里是编译错误:

And here is the compile error:

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

的方式I(MIS)了解的东西:

The way I (mis)understand things:

  1. 通过要求使用MyMacros,模块MyModule应该知道两个宏的存在.因此,我应该能够使用任何宏.
  2. 当print_hashes_around在MyModule的膨胀时,编译器应该发现,print_expr也是一个宏.因此,另一个膨胀应该发生.
  3. 有什么事发生的是,第二次膨胀不会发生.因此,编译器会寻找不存在的函数定义.

是吗?

如在松弛中建议的那样,在print_expr前面加上MyMacros.可以解决此问题.我还是不明白为什么. 要求这样既宏应该是已知的和可扩展的......当我看<4>,它使用,而不是<6>.

As suggested in slack, prefixing print_expr with MyMacros. fixes it. I still don't understand why. MyModule requires MyMacros so both Macros should be known and expandable... When I look at the definition of unless, it uses if, not Kernel.if.

推荐答案

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

By requiring MyMacros, the module MyModule should know the existence of both macros. Therefore I should be able to use any macros.

在误解是在这里. :) 仅使提供给编译器模块,它不进口的模块的功能.如果您使用<8>然后它会工作.

The misunderstanding is here. :) require only makes the module available to the compiler, it does not import the module functions. If you used import MyModule then it would work.

不过,这将是最好的前缀模块名来解决这个问题,因为这样你允许开发人员使用代码中使用您的宏明确(与<7>)或通过导入.

However, it would be best to fix the issue by prefixing the module name, because then you allow developers using your code to use your macros explicitly (with require) or by importing them.

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

Another option is to avoid multiple macro invocations like this:

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

这篇关于lix剂中的宏扩展:如何使用另一个定义两个宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆