Type inference for vcat

Hi all,

I’m just trying to understand the rules for type inference when using vcat. Consider the following operations on v0.7:

vcat(Int[], 1)
vcat(String[], "a")
vcat(UnitRange{Int}[], 1:1)
vcat(Vector{Int}[], [1])

return respectively a Vector{Int}, Vector{String}, Vector{Any}, and Vector{Any}. Observing the first two operations, I would have thought the rule was for any type T, inputting values with types (Vector{T}, T) to vcat would return Vector{T}, but type inference seems to break down for the last two operations. Is this a bug, or indicative of some subtler behaviour that I’m not seeing?

EDIT: even weirder, note that:

julia> vcat([1:1], 1:1)
2-element Array{Any,1}:

How did I get an Int as the second element of the output!?! That definitely feels like a bug.



1 Like

I think you meant to write:

julia> vcat(Int[], [1])
1-element Array{Int64,1}:


julia> vcat(Vector{Int}[]..., [1]) 
1-element Array{Int64,1}:  

Hm, what would you have expected? vcat makes a vector consisting of all the elements of the first input and then all the elements of the second input. All elements of 1:1 are just 1.

1 Like

No, I definitely meant vcat(Vector{Int}[], [1]), since it was the input type pattern (Vector{T}, T) I was targeting in my test cases (in this case, T is Vector{Int}).

The behaviour I was expecting was for a call to vcat with input types (Vector{T}, T) to always result in Vector{T} output, eg I was expecting vcat([1:1], 1:1) to return [1:1, 1:1]. But what you said here

explains the source of my misunderstanding. My heuristic output type rule derived from the first two test-cases breaks down when T is a subtype of AbstractArray. And I can see the logic now for doing it the way it is done. It allows us to do really nice things like vcat([1,2,3], 4:6). In my head, I was imagining vcat([1,2,3], 4:6) would need to be written vcat([1,2,3], collect(4:6)).

Thanks for clearing up my misunderstanding. The only thing I’m still a bit hesitant about is why vcat(Int[], 1) is allowed at all? A scalar doesn’t really have any elements, so shouldn’t this op be an error? Or am I asking something that has been hashed out in a github issue long ago and doesn’t need to be revived? :slight_smile:


That was indeed discussed at length on github, but the conclusion was that numbers are iterable:

julia> for i in 1
       @show i
i = 1  

Thus they should be vcatable.


Understood. Thanks again for taking the time to explain.

You’re welcome. I think there is a “solved”-thingy you can click.

Note that inference isn’t involved here, these are actually promotion rules.

Yes, this whole thread really boils down to me thinking it was an inference issue and not a promotion issue :slight_smile: