David Parks
David Parks

Reputation: 32081

Julia multiple dispatch not matching subtypes

Can someone help me understand why this julia function definition isn't matched by my attempt to use it seen below?

My naive assumption is that the Array{ASCIIString,1} that is being passed into the function should match the function definition of Array{AbstractString,1}, and so on.

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>

Upvotes: 4

Views: 777

Answers (2)

AmanicA
AmanicA

Reputation: 5495

Since Colin's answer, the syntax of Julia changed. Since Julia version 1, it looks like this:

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

See: https://docs.julialang.org/en/v1/manual/methods/#Methods-1

Upvotes: 2

Colin T Bowers
Colin T Bowers

Reputation: 18560

I think it is worthwhile turning my two comments above into an answer.

As @DanGetz indicated, the important phrase here is invariant. In this particular case, this principle implies that ASCIIString <: AbstractString evaluates to true, but Array{ASCIIString, 1} <: Array{AbstractString, 1} evaluates to false. So for the function defined as in your question to work, you would need to pass in an array a with eltype(a) evaluating to AbstractString. Passing in a with eltype(a) evaluating to ASCIIString doesn't work, because this is not a subtype of Array{AbstractString, 1}.

To solve your problem, you need type parameters. If you want to only define the function for the case where the type of b matches eltype(a), then you would use:

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

If you want to allow the type of b to differ from eltype(a), but enforce b to be a subtype of AbstractString, you would use:

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

Upvotes: 7

Related Questions