v06我想写一个期望2到3个参数的签名.第一个是Integer或Vector of Integer.第二个是整数向量或整数矩阵.第三个是整数向量或未指定.
我第一次尝试这样
function foo(
a::Union{Integer, Vector{Integer}},
b::Union{Vector{Integer}, Matrix{Integer}},
c::Union{Void, Vector{Integer}} = nothing)
Run Code Online (Sandbox Code Playgroud)
当我这样称呼这个时,foo(3, [0o7, 0o5])
我收到一个错误,告诉我它无法匹配.
ERROR: LoadError: MethodError: no method matching foo(::Int64, ::Array{UInt8,1})
Closest candidates are:
foo(::Union{Array{Integer,1}, Integer}, !Matched::Union{Array{Integer,1}, Array{Integer,2}}) at ...
foo(::Union{Array{Integer,1}, Integer}, !Matched::Union{Array{Integer,1}, Array{Integer,2}}, !Matched::Union{Array{Integer,1}, Void}) at ...
Run Code Online (Sandbox Code Playgroud)
现在我明白了为什么朱莉娅无法Array{UInt8} <: Array{Integer} == false
与之匹敌,但这似乎并不是朱莉娅的聪明.
然后我尝试了这个
foo(a::Union{Z1, Vector{Z1}},
b::Union{Vector{Z2}, Matrix{Z2}},
c::Union{Void, Vector{Z3}} = nothing
) where {Z1 <: Integer, Z2 <: Integer, Z3 <: Integer}
Run Code Online (Sandbox Code Playgroud)
现在朱莉娅甚至没有告诉我什么不匹配!
ERROR: LoadError: MethodError: no method matching foo(::Int64, ::Array{UInt8,1}, ::Void)
Closest candidates are:
foo(::Union{Array{Z1<:Integer,1}, Z1<:Integer}, ::Union{Array{Z2<:Integer,1}, Array{Z2<:Integer,2}}, ::Union{Array{Z3<:Integer,1}, Void}) where {Z1<:Integer, Z2<:Integer, Z3<:Integer} at ...
foo(::Union{Array{Z1<:Integer,1}, Z1<:Integer}, ::Union{Array{Z2<:Integer,1}, Array{Z2<:Integer,2}}) where {Z1<:Integer, Z2<:Integer} at ...
Run Code Online (Sandbox Code Playgroud)
是的,Array{UInt8} <: Array{Integer} == false
.这称为"参数不变性".许多其他问题已经讨论过这个主题.
但是,您遇到的另一个问题是,当您使用静态函数参数时 - 也就是说,f(…) where T
- T
必须匹配某些东西,因为它可以在函数体中使用.这会导致麻烦Union
S其中,T
在每一个选项不可用.我相信有一个关于更改此行为以允许匹配Union
不包含的元素的公开问题T
,如果您尝试访问它,则会将该绑定转换为未定义的变量.
现在的解决方法是使用不是函数的静态参数的类型变量.例如,
foo(a::Union{Integer, Vector{<:Integer}},
b::Union{Vector{<:Integer}, Matrix{<:Integer}},
c::Union{Void, Vector{<:Integer}} = nothing) = 1
Run Code Online (Sandbox Code Playgroud)