我有一个像这样的嵌套字典
function_dict_1 = Dict(
:f => Dict(
:func1 => x -> x^2
)
)
我想调用一个强类型函数,它接收这个字典作为参数。
我的第一个想法是这样输入:
dict_arg::Dict{Symbol, Dict{Symbol, <:Function}}
但是,我遇到了不匹配的函数调用错误。
我很困惑,因为它似乎适用于其他数据类型:
string_dict = Dict(
:s => Dict(
:string1 => "a"
)
)
typeof(string_dict) <: Dict{Symbol, Dict{Symbol, String}}
>> true
以及非嵌套字典:
function_dict_2 = Dict(
:func1 => x -> x^2
)
typeof(function_dict_2) <: Dict{Symbol, <:Function}
>> true
我尝试了以下类型:
Dict{Symbol, Dict{Symbol, <:Function}}
Dict{Symbol, Dict{Symbol, Function}}
AbstractDict{Symbol, AbstractDict{Symbol, <:Function}}
AbstractDict{Symbol, AbstractDict{Symbol, Function}}
这一切都不起作用。
输入该变量的正确方法是什么?
function_dict_1::Dict{Symbol, <:Dict{Symbol, <:Function}}
您还可以使用显式通用参数来解决此问题:
function_dict_1::Dict{Symbol, Dict{Symbol, F}} where F <: Function
您可能想知道为什么这两种方法都有效,而
Dict{Symbol, Dict{Symbol, <:Function}}
却不起作用;毕竟,Dict{Symbol, Dict{Symbol, <:Function}}
和 Dict{Symbol, Dict{Symbol, F}} where F <: Function
不一样吗?不,因为隐式泛型参数的作用域始终是包含 {}
的最内层 <:
,因此 Dict{Symbol, Dict{Symbol, <:Function}}
实际上与 Dict{Symbol, Dict{Symbol, F where F <: Function}}
相同。
现在,除了元组之外,
T1 <: T2
并不意味着SomeType{T1} <: SomeType{T2}
。因此,即使 typeof(function_dict_1).parameters[2]
是 Dict{Symbol, var"#1#2"}
(其中 var"#1#2"
是匿名函数类型的名称)和 Dict{Symbol, var"#1#2"} <: Dict{Symbol, <:Function}
(但是 !(Dict{Symbol, var"#1#2"} <: Dict{Symbol, Function})
!),我们确实 not 有那个 Dict{Symbol, Dict{Symbol, var"#1#2"}} <: Dict{Symbol, Dict{Symbol, <:Function}}
。
那么为什么我上面给出的两个答案有效,而
Dict{Symbol, Dict{Symbol, <:Function}}
却不起作用?因为隐式泛型参数的作用域是包含 {}
的最里面 <:Function
,所以 outer 字典类型是具体类型,而不是 UnionAll
。
julia> dump(Dict{Symbol, Dict{Symbol, <:Function}})
Dict{Symbol, Dict{Symbol, <:Function}} <: AbstractDict{Symbol, Dict{Symbol, <:Function}}
slots::Memory{UInt8}
keys::Memory{Symbol}
vals::Memory{Dict{Symbol, <:Function}}
ndel::Int64
count::Int64
age::UInt64
idxfloor::Int64
maxprobe::Int64
由于
function_dict_1
不是完全这种类型,所以它不能是它的子类型。
现在,将其与我们得到的其他类型进行比较。为了使子类型起作用(元组除外),我们需要
UnionAll
或抽象类型作为最外层类型。
julia> dump(Dict{Symbol, <:Function})
UnionAll
var: TypeVar
name: Symbol #s66
lb: Union{}
ub: Function <: Any
body: Dict{Symbol, var"#s66"<:Function} <: AbstractDict{Symbol, var"#s66"<:Function}
slots::Memory{UInt8}
keys::Memory{Symbol}
vals::Memory{var"#s66"}
ndel::Int64
count::Int64
age::UInt64
idxfloor::Int64
maxprobe::Int64
julia> dump(Dict{Symbol, Dict{Symbol, F where F <: Function}})
Dict{Symbol, Dict{Symbol, Function}} <: AbstractDict{Symbol, Dict{Symbol, Function}}
slots::Memory{UInt8}
keys::Memory{Symbol}
vals::Memory{Dict{Symbol, Function}}
ndel::Int64
count::Int64
age::UInt64
idxfloor::Int64
maxprobe::Int64
julia> dump(Dict{Symbol, Dict{Symbol, F}} where F <: Function)
UnionAll
var: TypeVar
name: Symbol F
lb: Union{}
ub: Function <: Any
body: Dict{Symbol, Dict{Symbol, F<:Function}} <: AbstractDict{Symbol, Dict{Symbol, F<:Function}}
slots::Memory{UInt8}
keys::Memory{Symbol}
vals::GenericMemory{:not_atomic, Dict{Symbol, F<:Function}, Core.AddrSpace{Core}(0x00)}
ndel::Int64
count::Int64
age::UInt64
idxfloor::Int64
maxprobe::Int64
julia> dump(Dict{Symbol, <:Dict{Symbol, <:Function}})
UnionAll
var: TypeVar
name: Symbol #s67
lb: Union{}
ub: UnionAll
var: TypeVar
name: Symbol #s68
lb: Union{}
ub: Function <: Any
body: Dict{Symbol, var"#s68"<:Function} <: AbstractDict{Symbol, var"#s68"<:Function}
slots::Memory{UInt8}
keys::Memory{Symbol}
vals::Memory{var"#s68"}
ndel::Int64
count::Int64
age::UInt64
idxfloor::Int64
maxprobe::Int64
body: Dict{Symbol, var"#s67"<:(Dict{Symbol, <:Function})} <: AbstractDict{Symbol, var"#s67"<:(Dict{Symbol, <:Function})}
slots::Memory{UInt8}
keys::Memory{Symbol}
vals::Memory{var"#s67"}
ndel::Int64
count::Int64
age::UInt64
idxfloor::Int64
maxprobe::Int64
julia>