Macros seem to have a pretty weird way of dealing with keyword arguments, especially keyword arguments that are passed with ;
. It seems arguments after ;
are moved to the front of the macro call, except if the macro is combined with the do
syntax (then they’re moved to the second place). I came across this problem while trying to write my own version of DrWatson.@produce_or_load
(which includes code to handle this sort of situation).
To illustrate, consider this macro:
macro pr(exs...)
for (i, ex) in enumerate(exs)
print("$i: type $(typeof(ex))")
if ex isa Expr
print(" Head: $(repr(ex.head)); Args: $(ex.args)")
end
print("\n")
end
end
This produces the following:
julia> @pr(projectdir("name.jld2"), a=5; b=b, c) do
return nothing
end
1: type Expr Head: :->; Args: Any[:(()), quote
#= REPL[2]:2 =#
return nothing
end]
2: type Expr Head: :parameters; Args: Any[:($(Expr(:kw, :b, :b))), :c]
3: type Expr Head: :call; Args: Any[:projectdir, "name.jld2"]
4: type Expr Head: :kw; Args: Any[:a, 5]
julia> @pr(_ -> nothing, projectdir("name.jld2"), a=5; b=b, c)
1: type Expr Head: :parameters; Args: Any[:($(Expr(:kw, :b, :b))), :c]
2: type Expr Head: :->; Args: Any[:_, quote
#= REPL[3]:1 =#
nothing
end]
3: type Expr Head: :call; Args: Any[:projectdir, "name.jld2"]
4: type Expr Head: :(=); Args: Any[:a, 5]
I can sort of work around all of that behavior, but my actual question is: where is any of this documented? That would include moving around keyword arguments, and the meaning of the “special” heads :parameters
, :kw
, and :->
. I’m not finding any of these in Metaprogramming · The Julia Language. Is there some other resource that can serve as a reference for macro programming? Is any of this guaranteed to be stable between different Julia versions?