macro test1(name,arg)
println(arg.args[2])
typeof(arg.args[2])
end
@test1 test1 (
(arg1, (:max=>10))
)
I have the macro above and I'm trying to pass a Dict parameter as the second parameter. But the problem is that I cannot access it. The macro will always interpret the second parameter as an expression, and when I try to access arg.args[2].args
it shows:
Vector{Any} (alias for Array{Any, 1})
so I don't know how to pass the Dict as it is.
I just want to get the second argument like:
Dict{Symbol, Int64} with 1 entry:
:max => 10
CodePudding user response:
Macros don't work at the same phase as functions. Source code is first parsed to Symbol
s, literals (integers, floats, strings, etc), or Expr
(expressions). All expressions are built from these three things. It's easy to check which of the three, just fill in the blank typeof(:( ))
and check what comes out in the REPL. Macros do all their work on these expressions. It is only afterward that these expressions are compiled into working code, where more complicated objects like Dict
s can exist.
The code below illustrates the difference before and after compiling. Note how 1 5
and max
were an expression and a Symbol
in the macro body, but is afterward evaluated to an Int64
and a function.
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 max Int64 10 max::Int64
#= printout
Expr 1 5
Symbol max
Tuple{Symbol,Int64,Expr} (:Int64, 10, :(max::Int64))
=#
for item in evaluated println(typeof(item), " ", item) end
#= printout
Int64 6
typeof(max) max
Tuple{Symbol,Int64,Expr} (:Int64, 10, :(max::Int64))
=#
This also shows how a macro can take an arbitrary number of expressions in a tuple and can directly take a parts of a struct
expression, hope those will be good hints for your struct
project.