【问题标题】:How can I define a julia macro that defines a macro?如何定义定义宏的 julia 宏?
【发布时间】:2017-05-15 18:18:50
【问题描述】:

我原以为这会起作用:

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 的几次迭代,但我不知道如何将我的定义更改为让它工作。

【问题讨论】:

标签: macros julia


【解决方案1】:

在处理引用中的引用时,宏观卫生有点麻烦。通常我发现唯一的方法是完全拒绝宏观卫生,并随意使用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

【讨论】:

  • 谢谢!克里斯的评论让我非常接近,但还没有到达那里。我一直遇到this issue。令我惊讶的是,您的第二个解决方案没有遇到这个问题。我猜如果您转义 entire 表达式,则有关转义参数的错误将不适用。
  • @HaberdashPI 啊,是的,在我的第一个解决方案中,我最初忘记了转义 arg。但是,它也没有遇到这个问题。我们实际上并没有在这里转义任何函数参数名称。我已经更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-03
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多