lix剂中的宏扩展:如何使用另一个定义两个宏? [英] Macro expansion in elixir: how to define 2 macros with one using the other?
问题描述
我正在与宏在酏剂试验.因此,我将要显示的代码当然应该使用简单的函数完成,但是..我正在尝试!
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:
- 通过要求使用MyMacros,模块MyModule应该知道两个宏的存在.因此,我应该能够使用任何宏.
- 当print_hashes_around在MyModule的膨胀时,编译器应该发现,print_expr也是一个宏.因此,另一个膨胀应该发生.
- 有什么事发生的是,第二次膨胀不会发生.因此,编译器会寻找不存在的函数定义.
是吗?
如在松弛中建议的那样,在print_expr
前面加上MyMacros.
可以解决此问题.我还是不明白为什么.
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.
在误解是在这里. :)
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屋!