# Array concatenation results in type inconsistency

**URL:** <https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237>\
**Category:** Performance\
**Created:** [December 22, 2020, 5:40pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237 "2020-12-22T17:40:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![a-ill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/a-ill/32/20663_2.png) [@a-ill](https://discourse.julialang.org/u/a-ill)\
**Post date:** [December 22, 2020, 5:40pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/1 "2020-12-22T17:40:16Z")

</div>

Here is an example.

```julia
function test_func()
    array1 = rand(Float64,10,10)
    array2 = rand(Float64,10,10)
    out = cat(array1,array2,dims=1)
    return out
end

```

```julia
@code_warntype test_func()
Variables
  #self#::Core.Compiler.Const(test_func, false)
  array1::Array{Float64,2}
  array2::Array{Float64,2}
  out::Any

Body::Any
1 ─ (array1 = Main.rand(Main.Float64, 10, 10))
│ (array2 = Main.rand(Main.Float64, 10, 10))
│ %3 = (:dims,)::Core.Compiler.Const((:dims,), false)
│ %4 = Core.apply_type(Core.NamedTuple, %3)::Core.Compiler.Const(NamedTuple{(:dims,),T} where T<:Tuple, false)
│ %5 = Core.tuple(1)::Core.Compiler.Const((1,), false)
│ %6 = (%4)(%5)::Core.Compiler.Const((dims = 1,), false)
│ %7 = Core.kwfunc(Main.cat)::Core.Compiler.Const(Base.var"#cat##kw"(), false)
│ %8 = array1::Array{Float64,2}
│ (out = (%7)(%6, Main.cat, %8, array2))
└── return out

```

Both vcat and hcat work just fine though.

```julia
function test_func()
    array1 = rand(Float64,10,10)
    array2 = rand(Float64,10,10)
    out = vcat(array1,array2)
    return out
end

```

```julia
@code_warntype test_func()
Variables
  #self#::Core.Compiler.Const(test_func, false)
  array1::Array{Float64,2}
  array2::Array{Float64,2}
  out::Array{Float64,2}

Body::Array{Float64,2}
1 ─ (array1 = Main.rand(Main.Float64, 10, 10))
│ (array2 = Main.rand(Main.Float64, 10, 10))
│ (out = Main.vcat(array1, array2))
└── return out

```

Am I doing something wrong or is it a bug?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [December 22, 2020, 5:43pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/2 "2020-12-22T17:43:59Z")

</div>

The problem is that `cat` is a type unstable function because if `dims=3` then it would return a `10x10x2` array.

---

<div class="post-metadata">

**Author:** ![a-ill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/a-ill/32/20663_2.png) [@a-ill](https://discourse.julialang.org/u/a-ill)\
**Post date:** [December 22, 2020, 5:47pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/3 "2020-12-22T17:47:38Z")

</div>

Do you have any suggestions on how to concatenate arrays in a type stable manner along dimensions higher than 2?

---

<div class="post-metadata">

**Author:** ![a-ill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/a-ill/32/20663_2.png) [@a-ill](https://discourse.julialang.org/u/a-ill)\
**Post date:** [December 22, 2020, 6:09pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/4 "2020-12-22T18:09:43Z")

</div>

I checked Julia’s source code for `cat` and it seems that both `vcat` and `hcat` are defined using `cat`. I suppose that one can define his own type stable functions for concatenating arrays along higher dimensions.  
Here is an example for the third dimesion.

```julia
cat3(A::AbstractArray) = cat(A; dims=Val(3))
cat3(A::AbstractArray, B::AbstractArray) = cat(A, B; dims=Val(3))
cat3(A::AbstractArray...) = cat(A...; dims=Val(3))
function test_func()
    array1 = rand(Float64,10,10,10)
    array2 = rand(Float64,10,10,10)
    out = cat3(array1,array2)
    return out
end

```

```julia
@code_warntype test_func()
Variables
  #self#::Core.Compiler.Const(test_func, false)
  array1::Array{Float64,3}
  array2::Array{Float64,3}
  out::Array{Float64,3}

Body::Array{Float64,3}
1 ─ (array1 = Main.rand(Main.Float64, 10, 10, 10))
│ (array2 = Main.rand(Main.Float64, 10, 10, 10))
│ (out = Main.cat3(array1, array2))
└── return out

```

Is is the preferred way of doing that?

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [December 22, 2020, 6:57pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/5 "2020-12-22T18:57:43Z")

</div>

You are “hiding” the issue in that. If you do `@code_warntype cat3()`:

```julia
a1 = rand(Float64, 10, 10, 10)
a2 = rand(Float64, 10, 10, 10)
@code_typewarn cat3(a1, a2)

```

```julia
Variables
  #self#::Core.Compiler.Const(cat3, false)
  A::Array{Float64,3}
  B::Array{Float64,3}

Body::Array{Float64,3}
1 ─ %1 = (:dims,)::Core.Compiler.Const((:dims,), false)
│ %2 = Core.apply_type(Core.NamedTuple, %1)::Core.Compiler.Const(NamedTuple{(:dims,),T} where T<:Tuple, false)
│ %3 = Main.Val(3)::Core.Compiler.Const(Val{3}(), true)
│ %4 = Core.tuple(%3)::Core.Compiler.Const((Val{3}(),), false)
│ %5 = (%2)(%4)::Core.Compiler.Const((dims = Val{3}(),), false)
│ %6 = Core.kwfunc(Main.cat)::Core.Compiler.Const(Base.var"#cat##kw"(), false)
│ %7 = (%6)(%5, Main.cat, A, B)::Array{Float64,3}
└── return %7

```

---

<div class="post-metadata">

**Author:** ![a-ill](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/a-ill/32/20663_2.png) [@a-ill](https://discourse.julialang.org/u/a-ill)\
**Post date:** [December 22, 2020, 7:08pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/6 "2020-12-22T19:08:37Z")

</div>

I did not exactly understand what is wrong here. Could you elaborate on that? As I understand we aim to have all variable types in either blue or yellow after running `@code_typewarn` which indicates that the compiler is capable of compiling efficient machine code. Did I miss someting?

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [December 22, 2020, 7:15pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/7 "2020-12-22T19:15:30Z")

</div>

Sorry, I didn’t test fully. It appears is the difference between `dims=3` and `dims=Val(3)` if you are just looking to get rid of the red…

```julia
function test_func()
    array1 = rand(Float64,10,10)
    array2 = rand(Float64,10,10)
    out = cat(array1,array2,dims=Val(1))
    return out
end

@code_warntype test_func()

```

---

<div class="post-metadata">

**Author:** ![dmolina](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmolina/32/5246_2.png) [@dmolina](https://discourse.julialang.org/u/dmolina)\
**Post date:** [December 22, 2020, 7:15pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/8 "2020-12-22T19:15:36Z")

</div>

Have you tried:

```julia
function test_func2()
           array1 = rand(Float64,10,10)
           array2 = rand(Float64,10,10)
           out::Array{Float64,2} = cat(array1,array2,dims=1)
           return out
       end

```

In that way, type of out is well-know.  
**Edit:** solution from @pixel27 seems better.

---

<div class="post-metadata">

**Author:** ![simonschoelly](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonschoelly/32/21606_2.png) [@simonschoelly](https://discourse.julialang.org/u/simonschoelly)\
**Post date:** [December 22, 2020, 7:24pm UTC](https://discourse.julialang.org/t/array-concatenation-results-in-type-inconsistency/52237/9 "2020-12-22T19:24:10Z")

</div>

`vcat` and `hcat` might be defined in terms of `cat` in the general case, but for certain types there are special typed methods that are type stable:

[https://github.com/JuliaLang/julia/blob/549a73b99de47700ffe7b92beec9f84789682d38/stdlib/SparseArrays/src/sparsevector.jl#L1120](https://github.com/JuliaLang/julia/blob/549a73b99de47700ffe7b92beec9f84789682d38/stdlib/SparseArrays/src/sparsevector.jl#L1120)
