【问题标题】:Macro for a function template: escaping issues函数模板的宏:转义问题
【发布时间】:2016-10-15 03:08:07
【问题描述】:

我正在尝试为函数模板定义一个宏,即一个模板,您可以在其中轻松放入相关代码,但不想向用户公开所有细节实现细节。例如,我想要这样的东西,将表达式放入更复杂的函数中:

macro make_complex_function(ex)
  quote
    function (alg,f,t,u,k)
      # Add some stuff on top
      condition1 = false
      condition2 = false
      #...
      #Put in the user's code
      $(esc(ex))
      # Put a footer
      return some,stuff,here,long,annoying,list
    end
  end
end

因此用户可以轻松插入少量逻辑(使用简化的 API/文档):

easy_func = @make_complex_function begin
   if u > 1
      print("oh no! It happened!")
    end
 end

虽然更高级的用户仍然可以使用全部功能。但是,如果您运行该代码,您将可以访问未定义的引用错误。我认为这是因为我没有正确转义表达式,应该以某种方式转义整个函数,但不知道如何。

【问题讨论】:

    标签: metaprogramming julia


    【解决方案1】:

    简短回答:不要使用 esc 或将其放在整个 quote 块上。

    julia> macro m(e)
             quote
               function f(x)
                 return $(e)
               end
             end
           end
    @m (macro with 1 method)
    
    julia> f = @m x+1
    #1#f (generic function with 1 method)
    
    julia> f(2)
    3
    
    julia> macro m(e)
             esc(quote
               function f(x)
                 return $(e)
               end
             end)
           end
    @m (macro with 1 method)
    
    julia> f = @m x+1
    f (generic function with 1 method)
    
    julia> f(2)
    3
    

    长答案

    1. 关于卫生的事情

    julia 将为宏中定义的任何名称添加前缀,使它们在其他任何地方都无法访问。 esc 将取消这些前缀,以便最终表达式中的名称与您所写的完全相同。所以请记住,如果您需要在宏外部访问这些变量,请记住仅使用esc,而您的示例并非如此。

    1. 使用macroexpand 帮助构建宏

    例如,如果您将esc 放在错误的位置,如下所示:

    macro m(e)
        quote
            function f(x)
                return $(esc(e))
            end
        end
    end
    

    你会得到这样的表达:

    julia> macroexpand( :( @m x+1 ) )
    quote  # REPL[9], line 3:
        function #1#f(#2#x) # REPL[9], line 4:
            return x + 1
        end
    end
    

    您会发现f 及其参数以一个特殊的东西为前缀(因为它们没有被转义),而正文只是x,它没有在任何地方定义。

    1. 更好地使用函数而不是宏

    一般来说,最好使用高阶函数来实现“函数模板”,因为它们更易于阅读并且可以利用现代静态分析工具——尽管 Julia 似乎还没有:)。编写函数签名并传递它们看起来很烦人,但值得。

    【讨论】:

    • “编写函数签名并传递它们看起来很烦人,但值得。”与往常一样,这取决于您在做什么。
    猜你喜欢
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    相关资源
    最近更新 更多