假设我想
@fn a :b :c sort=true
扩展到
gn(a, :b, :c, sort=true)
目前,我正在撰写此内容
macro fn(x, args..., kwargs...)
esc(:(gn($x, $(args...), $(kwargs...))))
end
这似乎不起作用。
我如何扩展kwargs...
,就像宏一样?
无论如何,你都需要使用冒号来区分args和kwargs,但是:
julia> macro fn(x, args...; kwargs...)
esc(:(gn($x, $(args...), $(kwargs...))))
end
ERROR: syntax: macros cannot accept keyword arguments
Stacktrace:
[1] top-level scope at REPL[2]:1
当然,您可以自己解析“伪关键字参数”。它们只是作为赋值语句传递:
julia> dump(:(@fn a :b :c sort=true))
Expr
head: Symbol macrocall
args: Array{Any}((6,))
1: Symbol @fn
2: LineNumberNode
line: Int64 1
file: Symbol REPL[5]
3: Symbol a
4: QuoteNode
value: Symbol b
5: QuoteNode
value: Symbol c
6: Expr
head: Symbol =
args: Array{Any}((2,))
1: Symbol sort
2: Bool true
以下是遵循@phipsgabler评论的完整代码:
function gn(x, args...;kwargs...)
println("I am called with x=$x args=$args kwargs=$kwargs")
end
macro fn(x, args...)
aargs = []
aakws = Pair{Symbol,Any}[]
for el in args
if Meta.isexpr(el, :(=))
push!(aakws, Pair(el.args...))
else
push!(aargs, el)
end
end
quote
gn($x, $aargs...; $aakws...)
end
end
测试:
julia> @fn sin 1 2 3 x=4 y=8
I am called with x=sin args=(1, 2, 3) kwargs=Base.Iterators.Pairs(:x => 4,:y => 8)
Meta.isexpr(el, :(=))
作为条件。 - phipsgabler