Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia: How do I use kwargs… in macros?

Tags:

macros

julia

Say I want

@fn a :b :c sort=true

to expand to

gn(a, :b, :c, sort=true)

and currently, I am writing it as

macro fn(x, args..., kwargs...)
    esc(:(gn($x, $(args...), $(kwargs...))))
end

which doesn't seem to work.

How do I expand the kwargs... is a macro as is?

like image 365
xiaodai Avatar asked Nov 26 '25 09:11

xiaodai


2 Answers

In any case you'd have to separate args and kwargs by a colon, but:

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

However, you are of course free to parse "fake keyword arguments" yourself. They are simply passed as assignment statements:

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
like image 128
phipsgabler Avatar answered Nov 28 '25 00:11

phipsgabler


Here is the full code following the comment by @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

Testing:

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)
like image 34
Przemyslaw Szufel Avatar answered Nov 28 '25 00:11

Przemyslaw Szufel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!