# 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:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [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/1 "2018-05-31T17:29:29Z")

</div>

When initializing an array variable (whose size is unknown at the time), I often write `a= Array{Int}()` or `r = Array{Rational}()`, and then get an error when I try to `push!` into it later (` no method matching push!(::Array{Rational,0}, ::Rational{Int64})`).

It seems to me that it will be convenient if the constructor for `Array{Int64,N} where N` assumed N was 1, instead of assuming it 0 when left unspecified. I realize I can always write `Array{Int, 1}` or even better, `Vector{Int}` instead, but this seems like it would be a convenient shorthand for the common case of wanting an 1-dimensional array, and more useful than getting back a 0-dimensional array.

But may be I’m missing the intent behind this, so is there a reason such a constructor call gives you back an `Array{T, 0}` and not `Array{T, 1}`?

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [May 31, 2018, 5:33pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/2 "2018-05-31T17:33:26Z")

</div>

The size of a zero-dimensional array is `()`. That is, it has no dimensions. Thus, when you call the `Array` constructor with no dimensions, it instantiates a zero-dimensional array.

To construct a zero-length vector with a similar sort of shorthand, you can use `Vector{Int}()` instead. Or you can pass one explicit zero-length dimension like `Array{Int}(0)` — but that’s changing to `Array{Int}(undef, 0)` in 0.7.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [May 31, 2018, 5:38pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/3 "2018-05-31T17:38:54Z")

</div>

You can also use something even simpler, `Int[]`, that’s what I always use.

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [May 31, 2018, 5:55pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/4 "2018-05-31T17:55:54Z")

</div>

> [@mbauman](#):
>
> That is, it has no dimensions. Thus, when you call the `Array` constructor with no dimensions, it instantiates a zero-dimensional array.

That kinda makes sense in linguistic terms, but in programming terms we usually don’t take missing argument x to mean x doesn’t exist or is 0, we usually expect it to have a sane default. To take a random example, when calling `isapprox(3.1415926535, π)`, isapprox doesn’t assume `rtol` should be zero because it’s left unspecified, it takes a reasonable default value appropriate to the usage. In my view, `Array{Int}` leaves the dimension parameter unspecified, and like any optional argument it should take the most commonly expected value as its default. It’s a minor thing, but little things like this add up to make the language easier to use.

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [May 31, 2018, 6:03pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/5 "2018-05-31T18:03:20Z")

</div>

> [@digital\_carver](#):
>
> like any optional argument it should take the most commonly expected value as its default.

I don’t necessarily agree that this would be the most commonly expected value. To me a rank-n array has n indices. If I do `Array{Int}(undef)` then I’ve specified the dimensions of 0 of them. Note also that you can use `Vector{Int}` as a constructor, but you will still need the `0`.

---

<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 1, 2018, 9:37am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/6 "2018-06-01T09:37:54Z")

</div>

> [@digital\_carver](#):
>
> In my view, `Array{Int}` leaves the dimension parameter unspecified, and like any optional argument it should take the most commonly expected value as its default.

Your view is mistaken; as described in the docstring of `Array`,

> `dims` may be a tuple or a series of integer arguments corresponding to the lengths in each dimension.

so `Array{Int}()` is provided a series of integer arguments, which just happens to be empty. This is nice and consistent with all the syntactic variations.

Arguing from expectations is always tricky, as they can be very heterogeneous depending on the programmers previous experience with other languages and language design. Enforcing consistency is much easier to implement.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [June 1, 2018, 2:58pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/7 "2018-06-01T14:58:01Z")

</div>

> [@digital\_carver](#):
>
> That kinda makes sense in linguistic terms, but in programming terms we usually don’t take missing argument x to mean x doesn’t exist or is 0, we usually expect it to have a sane default.

`Array{T}(dims...)` in general is a varargs constructor where the number of arguments determines the number of dimensions of the resulting array. How many arguments are there in the call `Array{T}()`?

---

<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 1, 2018, 7:04pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/8 "2018-06-01T19:04:07Z")

</div>

Maybe `Vector{Int}()` or more generally `Array{Int,p}()` should create empty arrays of the specified shape. ( the latter case is actually convenient as `Array{Int,p}(zeros(Int,p)...)` is rather ugly.)

---

<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 2, 2018, 12:02pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/9 "2018-06-02T12:02:33Z")

</div>

> [@dlfivefifty](#):
>
> `Array{Int,p}()` should create empty arrays of the specified shape.

The `{}` syntax after types is usually used for type parameters, which don’t include `size` for an array, just `ndims`. So if you understand your suggestion correctly, it would be somewhat confusing.

---

<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 2, 2018, 12:19pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/10 "2018-06-02T12:19:14Z")

</div>

Yes I know that. I’m saying that it creates an empty array of. The specified shape: `Array{T,2}() ` would create a 0 x 0 matrix. (Or just look at the code example I gave for the general `p`).

---

<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 2, 2018, 12:43pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/11 "2018-06-02T12:43:46Z")

</div>

> [@dlfivefifty](#):
>
> `Array{T,2}()` would create a 0 x 0 matrix

I missed the use case for that, can you give an example? Eg `Vector{T}()` is used because I can `push!` into it, but I don’t think I have ever created an array with size `(0, 0, ..., 0)`.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [June 2, 2018, 12:47pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/12 "2018-06-02T12:47:38Z")

</div>

> [@Tamas\_Papp](#):
>
> I missed the use case for that, can you give an example? Eg `Vector{T}()` is used because I can `push!` into it, but I don’t think I have ever created an array with size `(0, 0, ..., 0)` .

Create an empty spot in a mutable struct to bind another array to later.

---

<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 2, 2018, 2:00pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/13 "2018-06-02T14:00:48Z")

</div>

Thanks for the example. I am not sure if the use case warrants a function in `Base` though.

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [June 2, 2018, 2:42pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/14 "2018-06-02T14:42:00Z")

</div>

How is a zero-dimensional array ever useful?

---

<div class="post-metadata">

**Author:** ![richardreeve](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/richardreeve/32/2257_2.png) [@richardreeve](https://discourse.julialang.org/u/richardreeve)\
**Post date:** [June 2, 2018, 2:42pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/15 "2018-06-02T14:42:32Z")

</div>

I think this is the point at which a consistency argument comes in though.

It never occurred to me that Array{Int, 3}() _wouldn’t_ create an empty 3-dimensional array until just now, given I’ve used Int and Vector{Int}() in the past. Not having the empty constructor is a completely unnecessary gotcha given Array{Int, 1}() and it’s obvious what it’ll do [and I can imagine using it exactly as @ChrisRackauckas suggests].

---

<div class="post-metadata">

**Author:** ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)\
**Post date:** [June 2, 2018, 3:42pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/16 "2018-06-02T15:42:11Z")

</div>

> [@richardreeve](#):
>
> It never occurred to me that Array{Int, 3}() _wouldn’t_ create an empty 3-dimensional array until just now

It throws an error because you didn’t give it 3 dimension arguments, to maintain consistency across all array constructors. The same goes for `Vector{Int}(undef)`.

I think I agree that `Array{T,N}(undef)` creating rank-`N` arrays with all 0 dimensions would be sensible, this is of course not the same thing as `Array{T}(undef)`, though I’m not sure I see many use cases for this. I always try pretty hard to allocate the entire array first and not push.

---

<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 2, 2018, 6:12pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/17 "2018-06-02T18:12:50Z")

</div>

> I think I agree that `Array{T,N}(undef)`

There’s no need for the `undef` if the array is empty: just `Array{T,N}()` would do. Note this is how it is even in Julia v0.7-alpha for `Vector`:

```julia
julia> Vector{Int}()
0-element Array{Int64,1}

julia> versioninfo
versioninfo (generic function with 4 methods)

julia> versioninfo()
Julia Version 0.7.0-alpha.20
Commit c8ce43ad17 (2018-06-02 06:26 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin17.5.0)
  CPU: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.0 (ORCJIT, skylake)
Environment:
  JULIA_VERSION = 0.6

```

---

<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 2, 2018, 6:15pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/18 "2018-06-02T18:15:01Z")

</div>

> [@tk3369](#):
>
> How is a zero-dimensional array ever useful?

Surprisingly, a zero dimensional array contains one entry:

```julia
julia> A = Array{Int,0}(undef)
0-dimensional Array{Int64,0}:
-1

julia> A[1] = 4
4

julia> A
0-dimensional Array{Int64,0}:
4

```

It’s very similar in usage to a `Ref`.

EDIT: This syntax makes the behaviour less bizarre looking:

```julia
julia> A[] = 3
3

julia> A
0-dimensional Array{Int64,0}:
3

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 2, 2018, 7:05pm UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/19 "2018-06-02T19:05:32Z")

</div>

There is definitely a trade-off being made between “consistency” and convenience here. How you see the consistency depends upon your viewpoint. I would argue that the `Vector{Int}()` constructor is the odd-one out and leads to this misunderstanding.

That said, now that we have the `undef` constructors in 0.7, the status is slightly different. No longer is `Array{Int}()` the logical extension of:

```julia
Array{Int}(dim1, dim2) -> Array{Int}(dim1) -> Array{Int}() # 2 -> 1 -> 0 dimensions

```

Instead, we have:

```julia
Array{Int}(undef, dim1, dim2) -> Array{Int}(undef, dim1) -> Array{Int}(undef)

```

So, then, there remain a few questions:

- What should `Array{Int}()` mean? I’d argue it should be an error — indeed it’s deprecated on 0.7 in favor of `Array{Int}(undef)` and will be a method error on 1.0. That seems sensible.
- What should `Array{Int, N}()` mean? This is deprecated for `N = 0` and is an error for all `N > 1`. When we last considered this, however, we didn’t have the new `undef`-ness. So now I suppose it’s no longer clashing with the above vararg dimensions, and could be taken to mean an “empty array.” We’d probably have to leave it as an error for `N=0` since you cannot have an empty 0-dimensional array. It somewhat makes sense that you wouldn’t need to specify `undef` for an empty array, but I’m still not entirely convinced this is a good idea. The good news is, however, that all of this design for 1.0 is erring slightly conservative and these would all be new features that could be introduced in 1.x.

---

<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, 9:29am UTC](https://discourse.julialang.org/t/why-does-array-int-product-array-int-0-and-not-array-int-1/11298/20 "2018-06-03T09:29:44Z")

</div>

> [@Tamas\_Papp](#):
>
> I missed the use case for that, can you give an example? Eg `Vector{T}()` is used because I can `push!` into it, but I don’t think I have ever created an array with size `(0, 0, ..., 0)` .

It’s useful as a type stable default argument value. Assuming for a moment that `Array{T, N}()` would create an empty array.

```julia
function f(x::Array{T, N}, weight = Array{T, N}()) where {T, N}
    if isempty(weight)
        # Compute unweighted special case.
    else
        # Compute the general case.
    end
end

```

Yes, you could use `nothing` to indicate no weight and being a small union it would probably be fast, but full type stability is still an attractive property.

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