我原以为这会起作用:
macro meta_meta(x,y)
:(macro $x(arg) :($($y) + $arg) end)
end
Run Code Online (Sandbox Code Playgroud)
预期的行为是调用@meta_meta(f,2)应该相当于 macro f(arg) :(2 + $arg) end
换一种说法:
julia> @meta_meta(f,2)
julia> @f(3)
5
Run Code Online (Sandbox Code Playgroud)
相反,我得到:
ERROR: syntax: invalid macro definition
Run Code Online (Sandbox Code Playgroud)
对于如何继续,我有点不知所措.我看到这个宏的表达式树与我手动生成@f并检查其表达式树的表达式不同,我尝试了几次@meta_meta的迭代,但是我无法弄清楚如何将我的定义更改为让它工作.
在报价中处理报价时,宏观卫生有点吝啬.我经常发现唯一的办法就是完全拒绝宏观卫生,并gensym自由地使用它来模拟它.
但是,在您的缩减示例中,将内部引用转换为Expr以下内容是直截了当的:
julia> macro meta_meta(x, y)
:(macro $(esc(x))(arg) Expr(:call, :+, $(esc(y)), esc(arg)) end)
end
@meta_meta (macro with 1 method)
julia> @meta_meta f 2
@f (macro with 1 method)
julia> @f 3
5
Run Code Online (Sandbox Code Playgroud)
如果事情变得更复杂,我上面提到的方法涉及关闭宏观卫生esc.这意味着我们必须自己做卫生,因此gensym:
julia> macro meta_meta(x, y)
arg = gensym()
esc(:(macro $x($arg) :($$y + $$arg) end))
end
@meta_meta (macro with 1 method)
julia> @meta_meta f 2
@f (macro with 1 method)
julia> @f 3
5
Run Code Online (Sandbox Code Playgroud)