# How are vectors of vectors type coerced?

I was having a bug in my code, which basically boils down to this.

``````inds = [1,2,3] # Vector{Int}
vals = [1.5, 2.5, 3.5] # Vector{Float64}
ivvec = [inds, vals] # Vector{Vector{Float64}}
ivvec[ivvec] #ERROR: ArgumentError: invalid index: 1.0 of type Float64
``````

The issue is this:

``````inds # Vector{Int}
ivvec # Vector{Float64}
``````

Even though `inds` is a `Vector{Int}`, `ivvec` is a `Vector{Float64}`. Once found, this bug is easy to fix. `ivvec = Any[inds, vals]` or `ivvec = (inds, vals)` both do the trick.

Another weird thing is that inds is copied, while vals is just referenced:

``````inds = 5 # 5
ivvec # 1.0
vals = 5.5 # 5.5
ivvec # 5.5
``````

Is this the intended behavior? What exactly is happening here?

I don’t have the time to dive into the specific details here, but a general advise: vectors of vectors are rarely a good design pattern in Julia. You have Matrix, N-dimensional Array, StructArrays.jl, Tables.jl and many other data structures that are suitable for efficient lookups with nested buffers.

One solution is to define a `Union`:

``````inds = [1,2,3] # Vector{Int}

vals = [1.5, 2.5, 3.5] # Vector{Float64}

ivvec = Union{Vector{Int},Vector{Float64}}[inds, vals]
``````

Otherwise, `ivvec` will be promoted to `Vector{Vector{Float64}}`.

1 Like

Typically, containers are referenced, but promotion breaks this behavior presumably because the values in the containers are not longer the same. The `Union` type should work as expected.

I am really surprised about this. I would have thought for sure it would automatically be a `Vector{Any}`. Breaking of the reference seems particularly odd.

What’s the rationale for doing promotion here? Or rather, what’s the general rule for when promotion happens?

1 Like

If they all have a common promotion type then they get converted to that type using `convert` and that type is the array’s `eltype`

A somewhat abstract advice is to use `Vector` for elements which are used for “the same thing”. In your particular example, it would be more tidy to use a `Tuple`:

``````ivvec = (inds, vals)
``````
2 Likes

Thanks for the info! I see a lot of people trying to “solve my problem,” when there’s a solution right there in the post. I was more just curious about why this happens and whether it’s a bug or a feature.

I guess each step makes sense as a rule,

• automatic promotion in a vector
• promoting a `Vector{Int}` into a `Vector{Float64}`
• copying promoted vectors but referencing non-promoted vectors
• not being able to use a `Float64` as an index

even if taken together they lead to some unintuitive behavior.

I guess if there are Julian lessons here, they are

1. Avoid vectors of vectors
2. Don’t make vectors of different things