Search code examples
functionjuliametaprogrammingdecorator

How to decorate a function in Julia?


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?


Solution

  • 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