Julia多重分派未匹配子类型

4

请问有人能帮我理解为什么我的julia函数定义不被我下面的使用尝试所匹配吗?

我天真地认为传入函数的Array{ASCIIString,1}应该与Array{AbstractString,1}的函数定义相匹配,依此类推。

julia> function test(a::Array{AbstractString,1}, b::AbstractString, c::Any) end
test (generic function with 1 method)

julia> test([""],"","")
ERROR: MethodError: `test` has no method matching test(::Array{ASCIIString,1}, ::ASCIIString, ::ASCIIString)
Closest candidates are:
  test(::Array{AbstractString,1}, ::AbstractString, ::Any)

julia>

1
原因是Julia类型是不变的,这意味着issubtype(Array{ASCIIString,1},Array{AbstractString,1})为false。请查看http://docs.julialang.org/en/release-0.4/manual/types/#man-parametric-types获取更多信息。 - Dan Getz
1
这是一个更简单的问题示例,与此问题不同的是问题的表述方式。然而,问题的呈现方式足够不同,我建议我们将其保持开放状态。为了快速参考,您需要的语法是function test{T<:AbstractString}(a::Array{T}, b::T, c::Any),尽管如果您想允许a的元素类型与b的类型不同,您可能需要第二个类型参数... - Colin T Bowers
1
抱歉,忽略我在之前评论中关于“第二类型参数”的胡言乱语。如果您想让a的元素类型和b的类型不同,则function test{T <: AbstractString}(a :: Array {T},b :: AbstractString,c :: Any)就足够了。关键点是ASCIIString<:AbstractStringtrue,但是Array{ASCIIString, 1} <: Array{AbstractString, 1}则为false - Colin T Bowers
2个回答

7
我认为将我上面的两条评论转化为答案是值得的。
正如@DanGetz所指出的那样,这里重要的短语是“不变量”。在这种特定情况下,这个原则意味着ASCIIString <: AbstractString评估为true,但Array{ASCIIString, 1} <: Array{AbstractString, 1}评估为false。因此,为了使问题中定义的函数工作,您需要传递一个数组a,其中eltype(a)评估为AbstractString。传递eltype(a)评估为ASCIIStringa是行不通的,因为它不是Array{AbstractString, 1}的子类型。
要解决您的问题,您需要使用类型参数。如果您只想为b的类型与aeltype匹配的情况下定义该函数,则应使用:
function test{T<:AbstractString}(a::Array{T}, b::T, c::Any)

如果你想要允许 b 的类型与 eltype(a) 不同,但是强制 bAbstractString 类型的子类型,那么你需要使用以下代码:

function test{T<:AbstractString}(a::Array{T}, b::AbstractString, c::Any)

讲解得非常好,谢谢!对于其他跟进这个问题的人,我需要查找一些东西:eltype(...)返回集合的类型,例如:eltype(Array{ASCIIString, 1}) # 返回:ASCIIString。此外,我发现这篇文章相关且有帮助:https://dev59.com/KWEi5IYBdhLWcg3wwecN。 - David Parks
@DavidParks 很高兴能帮忙! - Colin T Bowers

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接