I feel it should be obvious, but I can’t figure it out. Why does this work:
julia> function foo(::Type{<:AbstractArray{<:Integer}})
julia> foo(AbstractArray{<:Signed})
But not this:
julia> function bar(::Type{<:AbstractArray{T}}) where {T<:Integer}
julia> bar(AbstractArray{<:Signed})
ERROR: MethodError: no method matching bar(::Type{AbstractArray{#s47,N} where N where #s47<:Signed})
Closest candidates are:
bar(::Type{#s47} where #s47<:(AbstractArray{T<:Integer,N} where N)) where T<:Integer at REPL[3]:2
This works, however:
julia> bar(AbstractArray{Signed})
Do you really want to dispatch on the argument being a union type?
Because
foo(::Type{<:AbstractArray{<:Integer}})
means
foo(::Type{<:AbstractArray{T} where T <: Integer})
Do you really want to dispatch on the argument being a union type?
Actually yes, in this case. This was just a toy example, what’s actually provided is the a type to be read from data. So the user is supposed to just specify “I expect an array of integers” without giving the exact type.
I am curious what the purpose of this is. It will not yield fast code when the type is abstract. Also, AbstractArray{<:Integer}
will miss perfectly fine arrays of integers, such as
Any[1, 2, 3]
IMO well written Julia code should have results which are invariant to container types, except for result container types (not values!) and of course speed. A function that works on a Int[1, 2, 3]
should work on Any[1, 2, 3]
or Real[1, 2, 3]
, even if it is (significantly) slower.
1 Like
I am curious what the purpose of this is. It will not yield fast code when the type is abstract.
Definitely not - but I’m using it as a way for the user to express how some data is to be interpreted, semantically (data stored in HDF5). For example, is a matrix a matrix or a vector of vectors? Is an HDF5 group a table of columns? Semantics like that. So that dispatch is only run once every multi-megabytes, hence speed is not an issue.
I do have a workaround for this, I just wanted to understand what makes
foo(::Type{<:AbstractArray{<:Integer}})
different from bar(::Type{<:AbstractArray{T}}) where {T<:Integer}
when it comes to dispatch. The method error does list bar as a candidate, and in color mode, not part of it is colored as doesn’t match. But why doesn’t it match? Mainly, I was curious about what I’m missing about dispatch and type system here (probably something obvious).
Sure, I know it’s not the same as bar
, exactly. But why doesn’t dispatch find bar
?
The where T
outside the signature basically means there needs to be a specific T value, and AbstractArray{<:Signed}
does not have any specific value for T in AbstractArray{T}
.
4 Likes
The where T
outside the signature basically means there needs to be a specific T value
Thanks, @jeff.bezanson ! I never realized that (like @Tamas_Papp suggested I normally try hard to keep my code type stable ) - good to know!