如何在 julia 中创建多行宏?

how to to create a mulitline macro in julia?

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)

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

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

现在您可以按照您想要的方式调用它,它将return它的参数作为一个元组:

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"

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