如何在Julia中创建多行宏?

3
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

我不知道如何创建多行宏。我以为只需要添加begin和end,但我总是得到一个错误: MethodError: no method matching var"@Estruct"(::LineNumberNode, ::Module, ::Expr)

1个回答

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"

这段文字告诉你,该宏使用单个参数调用,该参数是一个头类型为:blockExpr,即一个引用块。要实现"多行宏",需要实现宏体来接受一个引用块表达式并处理它,可能通过查看其.args字段来完成,其中包含您感兴趣的所有表达式。您可能希望忽略其中的所有LineNumberNode对象,只处理块中的其他项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接