如何在 Julia 中装饰一个函数?

Dav*_*ira 6 metaprogramming function decorator julia

当我在 Julia 中编写程序包时,我编写了几个类似的函数:

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

    data |> @vlplot(:circle, x=x_col, y=y_col)
end
Run Code Online (Sandbox Code Playgroud)

现在的问题是,我实际上想kwargs在这个函数中实现,比如:

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

    data |> @vlplot(:circle, x=x_col, y=y_col;kwargs...)
end
Run Code Online (Sandbox Code Playgroud)

但由于@vlplot 是一个宏,这实际上不起作用。所以我需要实际使用元编程如下:

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
Run Code Online (Sandbox Code Playgroud)

问题是,如果我想使用“kwargs”,我想避免为我的每个函数编写这个循环,因此,如何做到这一点?

我的想法是以某种方式“装饰”每个功能,例如@decorate_with_kwargs scatterplot. 这可能吗?

Prz*_*fel 4

这是一种可能性:

function debugger(f, params...)
    @show f, params
    res = f(params...)
    @show res
    res
end
Run Code Online (Sandbox Code Playgroud)

现在测试:

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

julia> debugger(f, 2,3)
(f, params) = (f, (2, 3))
res = 5
5
Run Code Online (Sandbox Code Playgroud)

如果您的目标是kwargs在宏中进行处理,则方法如下:

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
Run Code Online (Sandbox Code Playgroud)