# Why does Array{Int}() product Array{Int, 0} and not Array{Int, 1}

**URL:** <https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298>\
**Category:** New to Julia\
**Created:** [May 31, 2018, 5:29pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298 "2018-05-31T17:29:29Z")\
**Posts on this page:** 13\
**Page:** 2

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 3, 2018, 10:10am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/21 "2018-06-03T10:10:07Z")

</div>

I would expect a `Union{Nothing, Array{T, N}}` to be optimized out in `v0.7`, especially if you branch anyway. In cases where it isn’t, a function barrier should take care of it, making the code also cleaner (although that is subjective; I happen to like small functions that do one thing only).

---

<div class="post-metadata">

**Author:** ![Iagoba\_Apellaniz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iagoba_apellaniz/32/34406_2.png) [@Iagoba\_Apellaniz](https://discourse.julialang.org/u/Iagoba_Apellaniz)\
**Post date:** [June 3, 2018, 11:09am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/22 "2018-06-03T11:09:27Z")

</div>

Is is not surprising since any element of an N-dimensional array `A` can be accessed by `A[a_1, a_2, ... a_N, 1, 1, ..., 1]`, note the arbitrary number of ones at the end.

For the specific case of a zero dimensional array, then, it has at least the `A[1, 1, ... 1]` element, which can be seen as the scalar version of the multidimensional arrays.

For short, a 2-dims array is a matrix, a 1-dim array is a vector and a 0-dims array is a scalar.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [June 3, 2018, 11:58am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/23 "2018-06-03T11:58:24Z")

</div>

> [@Tamas\_Papp](#):
>
> I would expect a `Union{Nothing, Array{T, N}}` to be optimized out in `v0.7` , especially if you branch anyway. In cases where it isn’t, a function barrier should take care of it, making the code also cleaner (although that is subjective; I happen to like small functions that do one thing only).

The union is optimized out in 0.7 but I’m not sure I understand the objection. Even if there are other options, it is still a valid use case.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 3, 2018, 12:10pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/24 "2018-06-03T12:10:07Z")

</div>

My objection is to introducing special constructors for this. Here the suggested use case is a sentinel value that fits in the type, once type stability is not a strict constraint other sentinel values are fine too, and maybe more conventional.

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [June 4, 2018, 3:02pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/25 "2018-06-04T15:02:22Z")

</div>

`Union{Missing, T}` is not 100% as fast as just using `T`, causes more allocations, and is not compatible with C code:

```julia
julia> struct Foo
       x::Int
       end

julia> struct FooM
       x::Union{Missing,Int}
       end

julia> function fillfoo(T,n)
       ret = Array{T}(undef, n)
       for k = 1:n
       ret[k] = T(1)
       ret
       end
       end

julia> @time fillfoo(Foo, 100000);
  0.046550 seconds (199.50 k allocations: 3.808 MiB)

julia> @time fillfoo(FooM, 100000);
  0.049624 seconds (299.50 k allocations: 8.385 MiB)

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 5, 2018, 7:24am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/26 "2018-06-05T07:24:53Z")

</div>

What you are measuring is sample noise. Both produce identical code in `v0.7`.

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [June 5, 2018, 8:16am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/27 "2018-06-05T08:16:42Z")

</div>

Look at the allocations. They are not identical.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 5, 2018, 8:28am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/28 "2018-06-05T08:28:36Z")

</div>

Naturally, since

```julia
julia> sizeof(Foo)
8

julia> sizeof(FooM)
16

```

as the extra information (the concrete type in the `Union`) needs to be represented.

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [June 5, 2018, 8:31am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/29 "2018-06-05T08:31:00Z")

</div>

So in high performance settings an empty array is twice as good as using `Missing` .

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 5, 2018, 9:03am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/30 "2018-06-05T09:03:42Z")

</div>

I don’t quite understand what you mean by “twice as good” — while memory allocation does affect performance, it does not translate linearly.

Also, I don’t understand how this came up in this topic. In [this example](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/20), one would not allocate a container at all, and in situations when one is needed, the memory cost would be a small fraction for the array (if it has elements).

Finally, in `v0.7`,

```julia
julia> struct A{N,T}
           inner::Array{N, T}
       end

julia> struct AM{N,T}
           inner::Union{Array{N, T}, Missing}
       end

julia> a = randn(10, 10, 10);

julia> Base.summarysize(A(a))
8056

julia> Base.summarysize(AM(a))
8056

```

so the compiler/memory management is now getting super-clever.

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [June 5, 2018, 9:12am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/31 "2018-06-05T09:12:43Z")

</div>

> I don’t quite understand what you mean by “twice as good” — while memory allocation does affect performance, it does not translate linearly.

Performance isn’t everything: memory usage matters.

> the memory cost would be a small fraction for the array

Depends on how many arrays there are.

Also, you ignored the other issues I raised (compatibility with C code). In any case, I think style-wise it’s a bad idea to use `Union{Missing,T}` when it’s only missing temporarily.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [June 5, 2018, 9:19am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/32 "2018-06-05T09:19:55Z")

</div>

> [@dlfivefifty](#):
>
> I think style-wise it’s a bad idea to use `Union{Missing,T}` when it’s only missing temporarily.

Probably this is where we disagree. I think that using `nothing` or `missing` instead of a sentinel value makes the code more readable (although I fully recognize this is subjective). The only exception is when the sentinel values are extremely well-established, such as `NaN`.

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [June 5, 2018, 9:28am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/33 "2018-06-05T09:28:57Z")

</div>

The issue is the type is user-facing: it’s misleading to the user to say it may be of type `Missing` if it’s only temporarily missing while setup.

Or another user case that comes up a lot is when your array is dynamically resized (I have a `CachedArray` type floating around that does this with lazy arrays). The natural initial size is 0 x 0: this is not to indicate it’s missing, just to indicate it’s currently empty.

Also, while `Union{T,Missing}` might be efficient in many settings, this is a compiler optimization trick that as a user we do not and can not appreciate the full impliciations of.

[Previous page](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298.md?page=1)
