首页 > 解决方案 > 在函数中解压 dict 条目

问题描述

我想解压存储在字典中的参数。之后它们应该在函数的本地范围内可用。名称应与作为符号的键相同。

macro unpack_dict()
    code = :()
    for (k,v) in dict
        ex = :($k = $v)
        code = quote
            $code
            $ex
        end
    end
    return esc(code)
end

function assign_parameters(dict::Dict{Symbol, T}) where T<:Any
    @unpack_dict
    return a + b - c
end

dict = Dict(:a => 1,
            :b => 5,
            :c => 6)

assign_parameters(dict)

但是,此代码抛出:

LoadError: UndefVarError: dict not defined

如果我在宏之前定义字典,它会起作用,因为字典已定义。

有人知道如何解决这个问题吗?使用eval()有效,但在我想要避免的全局范围内进行评估。

标签: julia

解决方案


如果你想解压它们,那么最好的方法是直接解压它们:

function actual_fun(d)
    a = d[:a]
    b = d[:b]
    c = d[:c]
    a+b+c
end

这将是类型稳定、相对快速且可读的。

例如,您可以执行以下操作(我为您提供了两个选项以避免直接分配给abc变量):

called_fun(d) = helper(;d...)
helper(;kw...) = actual_fun(;values(kw)...)
actual_fun(;a,b,c, kw...) = a+b+c

function called_fun2(d::Dict{T,S}) where {T,S}
    actual_fun(;NamedTuple{Tuple(keys(d)), NTuple{length(d), S}}(values(d))...)
end

现在您可以编写如下内容:

julia> d = Dict(:a=>1, :b=>2, :c=>3, :d=>4)
Dict{Symbol,Int64} with 4 entries:
  :a => 1
  :b => 2
  :d => 4
  :c => 3

julia> called_fun(d)
6

julia> called_fun2(d)
6

但我不推荐它——它的类型不稳定且可读性不强。

AFACT 其他可能性也会有类似的缺点,因为在编译期间 Julia 只知道变量的类型而不知道它们的值。

编辑:你可以这样做:

function unpack_dict(dict)
    ex = :()
    for (k,v) in dict
        ex = :($ex; $k = $v)
    end
    return :(myfun() = ($ex; a+b+c))
end

runner(d) = eval(unpack_dict(d))

然后运行:

julia> d = Dict(:a=>1, :b=>2, :c=>3, :d=>4)
Dict{Symbol,Int64} with 4 entries:
  :a => 1
  :b => 2
  :d => 4
  :c => 3

julia> runner(d)
myfun (generic function with 1 method)

julia> myfun()
6

但又一次 - 我觉得这有点乱。


推荐阅读