如何定义定义宏的julia宏?

时间:2017-05-15 18:18:50

标签: macros julia

我原以为这会起作用:

macro meta_meta(x,y)
  :(macro $x(arg) :($($y) + $arg) end)
end

预期的行为是调用@meta_meta(f,2)应该等同于macro f(arg) :(2 + $arg) end

换句话说:

julia> @meta_meta(f,2)
julia> @f(3)
5

相反,我得到:

ERROR: syntax: invalid macro definition

我对如何继续有点不知所措。我看到这个宏的表达式树与我手动生成@f并检查其表达式树的表达式不同,我已经尝试了几次@meta_meta的迭代,但我无法弄清楚如何更改我的让它运作的定义。

1 个答案:

答案 0 :(得分:6)

在处理报价中的报价时,宏观卫生有点吝啬。我经常发现唯一的办法就是完全拒绝宏观卫生,然后用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

如果事情变得更复杂,我上面提到的方法涉及用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