# 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}:
1:1
1
``````

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

Cheers,

Colin

1 Like

I think you meant to write:

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

or

``````julia> vcat(Vector{Int}[]..., [1])
1-element Array{Int64,1}:
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?

2 Likes

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

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

Thus they should be `vcat`able.

2 Likes

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