How to decorate a function in Julia?
Asked Answered
S

1

6

As I'm programming a package in Julia, I've written several functions of the sort:

function scatterplot(data; x_col=:x, y_col=:y)

    data |> @vlplot(:circle, x=x_col, y=y_col)
end

Now the thing is, I'd actually like to implement kwargs in this function, something like:

function scatterplot(data; x_col=:x, y_col=:y; kwargs...)

    data |> @vlplot(:circle, x=x_col, y=y_col;kwargs...)
end

But since @vlplot is a macro, this doesn't actually work. So to I need to actually use metaprogramming as the following:

function example(data;xcol,ycol,kwargs...)
    x = kwargs
    expression = "@vlplot(data=$data,mark=:point, x=$xcol, y=$ycol,"
    for (k,v) in x
        add = string(k,"=",v,",")
        expression = expression*add
    end
    expression = expression[1:end-1]*")"
    return expression
end

The thing is, I want to avoid having to write this loop for each of mine functions if I want to use "kwargs", hence, how can one do this?

My idea was to somehow "decorate" each function such as @decorate_with_kwargs scatterplot. Is this possible?

Sendai answered 24/11, 2020 at 17:2 Comment(10)
Basically you use metaprgramming or mutliple dispatrch for that. Your question is not quite clear because DoSomething(a,b,C) does not exist. How do you want it to be related to DoSomething(a,b)?Sympetalous
I guess you are right. It might be better to write macros instead.Sendai
I'll actually give the real example and expand on the question, so it becomes clearer.Sendai
Is your question on how to add kwargs to a macro?Sympetalous
Not really. I wanted to know if I could somehow add a wrapper to my functions, hence increasing their functionalitySendai
BTW it seems like there is totally no reason for @vlplot to be a macro instead of function. It is almost always a good idea to avoid writing new macros in your library.Sympetalous
Unfortunately @vlplot is from VegaLite, not myselfSendai
Dont't ypu have vlplot(args...; kwargs...)? - this should be the way to go.Sympetalous
Unfortunately no :(Sendai
Try using VegaLite;methods(VegaLite.vlplot) and see what happensSympetalous
S
4

Here is one possibility:

function debugger(f, params...)
    @show f, params
    res = f(params...)
    @show res
    res
end

And now testing:

julia> f(x,y) = x+y;

julia> debugger(f, 2,3)
(f, params) = (f, (2, 3))
res = 5
5

If your goal is handling kwargs in a macro here is how:

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
Sympetalous answered 24/11, 2020 at 17:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.