2

假设我有一个函数需要一个 dict 作为输入。在此范围内,此函数只能处理特定Union允许类型中的该 dict 的值。对于此参数,输入可以是NumberStringBool

allowed_types = Union{String, Int, AbstractFloat, Bool}

该函数还可以允许其值是这些允许的类型 ( Dict{String,allowed_types}) 的字典或项目是这些类型 ( ) 的数组,Array{allowed_types,Int}因为它们可以“反汇编”为这些允许的类型之一。(这可以继续向下 - 所以数组数组等)

full_allowed_types = Union{allowed_types, Dict{String,allowed_types}, Array{allowed_types,Int}}

然后我可以将我的功能定义为

function my_func(input::Dict{String,full_allowed_types})
...
end

那么,我如何构建我的函数参数以便我可以传递,IE my_func(Dict("a"=>"astr","b"=>1)),?通常,该Dict(...)调用会导致 a Dict{String,Any},它不能与我的函数一起调用,因为Any它不是允许的类型。

我当前实现的错误是:

my_func(Dict("a"=>"astr","b"=>1))
ERROR: MethodError: no method matching my_func(::Dict{String,Any})
Closest candidates are:
  my_func(::Dict{String,Union{Bool, Int64, Dict{String,Union{Bool, Int64, AbstractFloat, String}}, AbstractFloat, Array{Union{Bool, Int64, AbstractFloat, String},Int64}, String}}) at <snip>/my_func.jl:41
Stacktrace:
 [1] top-level scope at none:0

我从用户的角度来描绘这个问题,用户可能只是使用默认构造函数创建一个 dict,而不考虑my_func想要“允许”什么(这意味着我不希望他们调用Dict{String,my_pkg.full_allowed_types}(...))。

如果在我遍历输入时任何元素不符合我允许的类型,那么最好的选择是只允许Any作为输入然后抛出错误吗?my_func

4

2 回答 2

3

首先,在创建字典时,您可以像这样指定参数:

d = Dict{String, full_allowed_types}("a" => "astr", "b" => 2)

其次,您的创建my_func方式实际上是正确的,并且可以与d. 但是当你创建一个字典时

d2 = Dict{String, Int64}("a" => 1, "b" => 2)

你可能会感到惊讶,你不能my_funcd. 原因是,您只允许类型为的字典 Dict{String, full_allowed_types}Dict{String, Int64}即使Int64full_allowed_types. 如果您希望能够传递子类型,您可以声明my_func如下

function my_func(input::Dict{String, <: full_allowed_types})
    ...
end

注意<:这里的附加内容,这只是语法糖

function my_func(input::Dict{String, T}) where {T <: full_allowed_types}
    ...
end
于 2020-04-27T22:56:07.557 回答
3
function f(a::Dict{String, A}) where A <: Union{Int,String}
   println("Got elem type $A")
end

用法:

julia> f(Dict{String,Union{String,Int}}("a"=>"astr","b"=>1))
Got elem type Union{Int64, String}

现在,如果您想让用户方便,您可以添加一个额外的功能(但是,类型转换是有代价的):

function f(a::Dict{String,A}) where A
    @warn "Provided unsupported type of elements $A will try narrow it to Union{Int,String}"
    f(Dict{String,Union{Int,String}}(d))
end

示例用法:


julia> f(Dict("a"=>"astr","b"=>1))
┌ Warning: Provided unsuported type of elements Any will try narrow it to Union{Int,String}
└ @ Main REPL[31]:2
Got elem type Union{Int64, String}
于 2020-04-27T22:57:44.560 回答