【问题标题】:how to to create a mulitline macro in julia?如何在 Julia 中创建多行宏?
【发布时间】:2021-12-01 21:49:37
【问题描述】:
macro Estruct(name,arg,type,max=100,min=0,descritpion="")
        :(struct $(esc(name))
        $((esc(arg)))
        $(esc(name))($(esc(arg)))=new(
          check($(esc(type)),$(esc(arg)),$(esc(name)),$(esc(max)),$(esc(min)),$(esc(descritpion))))
       end)
end

我怎样才能像这样使用这个宏:

@Estruct begin
    B 
    arg1 
    Float64 
    200.0 
    5.0 
    "this"
end

我不知道如何制作多行宏。我以为我只需要添加开始和结束,但我总是得到:MethodError: no method matching var"@Estruct"(::LineNumberNode, ::Module, ::Expr)

【问题讨论】:

    标签: macros julia metaprogramming


    【解决方案1】:

    没有多行宏这样的东西,它只是一个将块作为参数的宏。您可以通过编写只返回其参数的虚拟版本来查看宏是如何被调用的:

    macro Estruct(args...); args; end
    

    现在你可以按照你想要的方式调用它,它会以元组的形式返回它的参数:

    julia> args = @Estruct begin
               B
               arg1
               Float64
               200.0
               5.0
               "this"
           end
    (quote
        #= REPL[12]:2 =#
        B
        #= REPL[12]:3 =#
        arg1
        #= REPL[12]:4 =#
        Float64
        #= REPL[12]:5 =#
        200.0
        #= REPL[12]:6 =#
        5.0
        #= REPL[12]:7 =#
        "this"
    end,)
    
    
    julia> typeof(args)
    Tuple{Expr}
    
    julia> dump(args[1])
    Expr
      head: Symbol block
      args: Array{Any}((12,))
        1: LineNumberNode
          line: Int64 2
          file: Symbol REPL[12]
        2: Symbol B
        3: LineNumberNode
          line: Int64 3
          file: Symbol REPL[12]
        4: Symbol arg1
        5: LineNumberNode
          line: Int64 4
          file: Symbol REPL[12]
        ...
        8: Float64 200.0
        9: LineNumberNode
          line: Int64 6
          file: Symbol REPL[12]
        10: Float64 5.0
        11: LineNumberNode
          line: Int64 7
          file: Symbol REPL[12]
        12: String "this"
    
    julia> args[1].args
    12-element Vector{Any}:
        :(#= REPL[12]:2 =#)
        :B
        :(#= REPL[12]:3 =#)
        :arg1
        :(#= REPL[12]:4 =#)
        :Float64
        :(#= REPL[12]:5 =#)
     200.0
        :(#= REPL[12]:6 =#)
       5.0
        :(#= REPL[12]:7 =#)
        "this"
    

    这告诉您宏被调用时使用了单个参数,该参数是 Expr,头部类型为 :block,即一个参数是带引号的块。要实现您的“多行宏”,您需要实现宏主体以接受带引号的块表达式并对其进行处理,大概是通过查看您感兴趣的所有表达式所在的 .args 字段。您可能希望忽略其中的所有 LineNumberNode 对象,而只处理块中的其他项目。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      相关资源
      最近更新 更多