为什么宏不能理解 Dict 参数?

ahm*_*hm5 5 macros dictionary expression julia

macro test1(name,arg)
    println(arg.args[2])
    typeof(arg.args[2])
end 

@test1 test1 (
  (arg1, (:max=>10))
)
Run Code Online (Sandbox Code Playgroud)

我有上面的宏,我试图传递一个 Dict 参数作为第二个参数。但问题是我无法访问它。该宏始终将第二个参数解释为表达式,当我尝试访问它时arg.args[2].args,它显示:

Vector{Any} (alias for Array{Any, 1})
Run Code Online (Sandbox Code Playgroud)

所以我不知道如何按原样传递字典。

我只想得到第二个参数,例如:

Dict{Symbol, Int64} with 1 entry:
  :max => 10
Run Code Online (Sandbox Code Playgroud)

Bat*_*aBe 3

这是因为宏在代码编译之前就对代码起作用。源代码首先被解析为Symbols、文字(整数、浮点数、字符串等)或Expr(表达式)。此时,所有表达式仅包含这三件事。** 宏完成并返回表达式后,该表达式被编译为运行时代码,其中Dict可以存在更复杂的对象(如 s)。

下面的代码说明了编译前后的差异。请注意宏体中的1+5和were 表达式,但随后被评估为 an和 a 。Dict()Int64Dict

                             # splat arbitrary number of Expr
macro peekExpr(expr1, expr2, expr3tuple...)
    println(typeof(expr1), "   ", expr1)
    println(typeof(expr2), "   ", expr2)
    println(typeof(expr3tuple), "   ", expr3tuple)
    :($expr1, $expr2, $expr3tuple)
end

evaluated = @peekExpr 1+5 Dict() Int64 10 max::Int64
#= printout
Expr   1 + 5
Expr   Dict()
Tuple{Symbol,Int64,Expr}   (:Int64, 10, :(max::Int64))
=#

for item in evaluated  println(typeof(item), "   ", item)  end
#= printout
Int64   6
Dict{Any, Any}   Dict{Any, Any}()
Tuple{Symbol,Int64,Expr}   (:Int64, 10, :(max::Int64))
=#
Run Code Online (Sandbox Code Playgroud)

**PS:请记住,Expr如果将运行时对象插入其中,则可以包含其他对象(x = Dict(); :(a in $x).args[end]vs :(a in Dict()).args[end])。只是宏在可以访问运行时对象的阶段不起作用。@peekExpr $x只会看到一个Expr(:$, :x).