Strange re-typing of arrays of numbers

Hello, I was putting together some multiple-dispatches to find that it doesn’t work as I would expect. Or rather, maybe dispatching works perfectly great, but my arrays of numbers get re-typed strangely.
When you have a list of lists of which all but one are integer lists:

x = [[2,3,4], [2,5], []]

it correctly assumes the type:
Array{Array{Any,1},1}

But if you afterwards try to extract the type of the first sub-list like so:

typeof(x[1])

It is surprisingly (for me) not a list of integers (but it is), but it is Array{Any,1}.

Could someone explain to me what is happening in the background? I wanted to use a parametric multiple dispatch that would handle list of sublists of the same type differently than a list of sublists of different types. So why doesn’t the type above get re-typed to list of integers? My multi-dispatch with which I discovered this behavior:

function(a::Vector{T}, b::Vector{T}) where {T}
    ..
end

function(a::Vector{T}, b::Vector{U}) where {T, U}
    ..
end

[] is a Vector{Any}, and literal array construction defaults to promoting all elements to the same type. Compare:

julia> x = [[2,3,4], [2,5], []]
3-element Array{Array{Any,1},1}:
 [2, 3, 4]
 [2, 5]
 []

julia> x = [[2,3,4], [2,5], Int[]]
3-element Array{Array{Int64,1},1}:
 [2, 3, 4]
 [2, 5]
 []

I think the latter is what you want.

If you really need the elements of the array to have different types, you need to declare the container to have an abstract type like Any:

julia> x = Any[[2,3,4], [2,5], []]
3-element Array{Any,1}:
 [2, 3, 4]
 [2, 5]
 Any[]

julia> x[1]
3-element Array{Int64,1}:
 2
 3
 4
3 Likes

This happened twice now in a short time. Compare:

Should there be a warning in the docs? Like, for example, here:

https://docs.julialang.org/en/v1/manual/arrays/#man-array-literals

Something along the lines of:

"Remember, promotion to a common type may also change the type of nested arrays:

julia> arr = [Int[1,2],[]]
3-element Array{Array{Any,1},1}:
 [1, 2]
 []

julia> arr[1]
2-element Array{Any,1}:
 1
 2

To prevent this, declare an abstract type for the containing array:

julia> arr2 = Any[[1,2],[]]
3-element Array{Any,1}:
 [1, 2]
 Any[]

julia> arr2[1]
2-element Array{Int64,1}:
 1
 2

"

1 Like