v06 我想写一个期望2到3个参数的签名。第一个是Integer或Integer矢量。第二个是整数矢量或整数矩阵。第三个是整数矢量或未指定。Julia无法多次发送
我第一次尝试像这样
function foo(
a::Union{Integer, Vector{Integer}},
b::Union{Vector{Integer}, Matrix{Integer}},
c::Union{Void, Vector{Integer}} = nothing)
当我把这种喜欢这个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 ...
现在我明白为什么Julia是无法匹配此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}
现在朱莉娅甚至没有告诉我什么不匹配!
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 ...
当你有这样非常复杂的类型签名,特别是有很多联合时,它可能是一个标志,你应该把它分成几个单独的方法定义。特别是,你可能希望至少避免使用'foo(a,b,c = Nothing)',而采用'foo(a,b,c)'和'foo(a,b)'。另外,请考虑这些类型之间是否存在关联,例如,仅当'b'是'Matrix'时'a' a'Vector'? – DNF
@DNF我明白你的关注。问题是,如果我这样做,用户得到无用的茱莉亚错误消息,而不是我写的有用的。例如。 “没有方法存在,你有一个矩阵为b和c是Void”,我宁愿像这样“如果你指定b作为矩阵,你必须指定c为这些维度的向量。事实上,这个签名是检查所有内容并将所有内容都转换为正确类型后调用真实方法的废话检查签名。 – Nozdrum
您正在设置自己去做大量的显式输入检查,这与多次调度的想法背道而驰。你只是为了避免让人们接触到普通的Julia错误信息而造成很大的痛苦。另外,如果我没有提供任何'c',我会惊讶地发现'c'是'Void'!建议:用正确的签名将你的功能分解成单独的方法。然后制作一个后备方法(或多个),以捕获剩下的部分:'f(a,b,c)= ...'没有类型,然后让那个人找出输入有什么问题并发出错误。 – DNF