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