# 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[2][ivvec[1]] #ERROR: ArgumentError: invalid index: 1.0 of type Float64
``````

The issue is this:

``````inds # Vector{Int}
ivvec[1] # Vector{Float64}
``````

Even though `inds` is a `Vector{Int}`, `ivvec[1]` 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[1] = 5 # 5
ivvec[1][1] # 1.0
vals[1] = 5.5 # 5.5
ivvec[2][1] # 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.

If your provide more details about your use case, someone might be able to extend juliohmâ€™s advice.

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