Reputation: 32081
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
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
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