# Types, strange behavior

**URL:** https://discourse.julialang.org/t/types-strange-behavior/51384
**Category:** General Usage
**Created:** [December 7, 2020, 8:16am UTC](https://discourse.julialang.org/t/types-strange-behavior/51384 "2020-12-07T08:16:58Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![rapasite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rapasite/32/3719_2.png) [@rapasite](https://discourse.julialang.org/u/rapasite)
#### Post date: [December 7, 2020, 8:16am UTC](https://discourse.julialang.org/t/types-strange-behavior/51384/1 "2020-12-07T08:16:58Z")

</div>

Julia Version 1.5.3 (2020-11-09)

Hi, looking at this

```julia
vector=[[1,2],[3,[4,5]]]
vector[1]
typeof(vector[1])

julia> vector=[[1,2],[3,[4,5]]]
2-element Array{Array{Any,1},1}:
 [1, 2]
 [3, [4, 5]]
julia> vector[1]
2-element Array{Any,1}:
 1
 2
julia> typeof(vector[1])
Array{Any,1}

```

Is there a good reason Julia cannot define the type to be Vector{Int64}?

---

<div class="post-metadata">

### Author: ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)
#### Post date: [December 7, 2020, 9:15am UTC](https://discourse.julialang.org/t/types-strange-behavior/51384/2 "2020-12-07T09:15:19Z")

</div>

Julia prefers to give a specific type to the outer container: `vector` is an `Array{Array{Any,1},1} === Vector{Vector{Any}}` rather than `Vector{Any}`. So the type of each element is `Vector{Any}`. And a `Vector{Int64}` is not a subtype of `Vectory{Any}` so it cannot store `[1,2]` as `Vector{Int64}`.

If you prevent Julia from using a specific type for the outer container, it works as you want:

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

julia> typeof(vector[1])
Array{Int64,1}

```

or

```julia
julia> vector = Any[[1,2], [3,[4,5]]];

julia> typeof(vector[1])
Array{Int64,1}

```

I think this is the expected behavior. The manual [says](https://docs.julialang.org/en/v1/manual/arrays/):

> Arrays can also be directly constructed with square braces; the syntax `[A, B, C, ...]` creates a one dimensional array (i.e., a vector) containing the comma-separated arguments as its elements. The element type ([`eltype`](https://docs.julialang.org/en/v1/base/collections/#Base.eltype)) of the resulting array is automatically determined by the types of the arguments inside the braces. If all the arguments are the same type, then that is its `eltype` . If they all have a common [promotion type](https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#conversion-and-promotion) then they get converted to that type using [`convert`](https://docs.julialang.org/en/v1/base/base/#Base.convert) and that type is the array’s `eltype` . Otherwise, a heterogeneous array that can hold anything — a `Vector{Any}` — is constructed; this includes the literal `[]` where no arguments are given.

---

<div class="post-metadata">

### Author: ![FPGro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fpgro/32/20822_2.png) [@FPGro](https://discourse.julialang.org/u/FPGro)
#### Post date: [December 7, 2020, 10:38am UTC](https://discourse.julialang.org/t/types-strange-behavior/51384/3 "2020-12-07T10:38:44Z")

</div>

Sudete already answered your question, but I still find it interesting to trace what happens here:  
Incidentally:

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

```

but:

```julia
julia> [[1,2],[[3,],[4,5]]]
2-element Array{Array{T,1} where T,1}:
 [1, 2]
 [[3], [4, 5]]

```

It boils down to the following:  
Julia uses promote\_rule to find a common type for the array elements:

```julia
julia> typeof([1,2])
Array{Int64,1}

julia> typeof([3,[4,5]])
Array{Any,1}

julia> promote_rule(Array{Int64,1}, Array{Any,1})
Array{Any,1}

```

which ultimately calls this to decide which type to promote to:

```julia
julia> Base.el_same(Any, Array{Int64,1}, Array{Any,1})
Array{Any,1}

```

from here: [https://github.com/JuliaLang/julia/blob/c31d126ac7ee425f3e121c16016844fb64a0c950/base/range.jl#L949](https://github.com/JuliaLang/julia/blob/c31d126ac7ee425f3e121c16016844fb64a0c950/base/range.jl#L949)

which basically says:  
If one of the containers doesn’t need to change in type, take that one. If that doesn’t work, make a typejoin. (a typejoin would give you your expected result here, an `Array{T,1} where T`)

Ultimately, someone decided that it is better to have a concrete type if possible and only fallback to Union types if that doesn’t work.  
That makes me think it’s intended behaviour, maybe necessary for good performance. I can’t give you more information on whether that is fully intended. Rules come from this commit:

[https://github.com/JuliaLang/julia/pull/22757](https://github.com/JuliaLang/julia/pull/22757)

So (and I hope thats not inappropriate) we might need to ask @jeff.bezanson about this.
