# Tuple as argument for size(AbstractArray)

**URL:** <https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533>\
**Category:** General Usage\
**Created:** [March 19, 2021, 12:18pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533 "2021-03-19T12:18:16Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [March 19, 2021, 12:18pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/1 "2021-03-19T12:18:16Z")

</div>

It would be great to have an alternative way of calling size with a tuple of dimensions.  
Is there a specific reason that this does not exist in Base?  
The function could look like

```julia
function size(x::AbstractArray{T},dim::NTuple{N,Int}; keep_dims=true) where{T,N}
    if ~keep_dims
        return map(n->size(x,n),dim)
    end
    sz=ones(Int, ndims(x))
    for n in dim
        sz[n]=size(x,n) 
    end
    return Tuple(sz)
end 

```

It can be used like this:

```julia
julia> x=ones(10,11,12);

julia> size(x,(2,3))
(1, 11, 12)

julia> size(x,(3,2), keep_dims=false)
(12, 11)

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [March 19, 2021, 1:37pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/3 "2021-03-19T13:37:42Z")

</div>

FWIW,

```julia
julia> x=ones(10,11,12);

julia> size.(Ref(x),(2,3))
(11, 12)

julia> size.(Ref(x),(3,2))
(12, 11)

```

---

<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:** [March 19, 2021, 1:41pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/4 "2021-03-19T13:41:12Z")

</div>

> [@RainerHeintzmann](#):
>
> ```julia
> julia> size(x,(2,3))
> (1, 11, 12)
> 
> ```

Well, that’s one reason. That works backwards from what I’d expect. 🙂

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [March 19, 2021, 3:01pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/5 "2021-03-19T15:01:14Z")

</div>

Not quite sure I understand. The idea was that if `keepdims` is true, it returns a size vector that is not squeezed in any way. I.e. with the original number of dimensions. Yet, if `keepdims` is false it is intentional that you obtain a tuple with the sizes in the order you are asking. Even multiple repetitions of the same size being allowed. Both of these modes are quite useful when it comes to writing array classes and alike.

---

<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:** [March 19, 2021, 3:22pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/6 "2021-03-19T15:22:59Z")

</div>

The point is that for something to be incorporated into Base, we’ve all gotta agree on how it’s going to work, and ideally it should be unambiguous. I’d expect `size(x, (2, 3))` to just be `(11, 12)`. I know you have an optional argument there, but that doesn’t really resolve the tension… it just makes it more complicated.

We’ve added optimized support for `size(x)[2:end]` for precisely these sorts of use-cases. Also, I’d point you towards working with axes and/or CartesianIndices a bit more.

---

<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:** [March 19, 2021, 4:11pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/7 "2021-03-19T16:11:57Z")

</div>

> [@RainerHeintzmann](#):
>
> Is there a specific reason that this does not exist in Base?

Generally, to have something in `Base`, you need compelling reasons in favor of, instead of a lack of reasons against including it. Also, Julia’s design favors flexible building blocks which you, the programmer, can combine to get what you need.

That said, in addition to broadcasting as suggested by @carstenbauer, you can also just destructure the result:

```julia
_, d2, d3 = size(x) # assuming you need d2 and d3 in a calculation

```

or use indexing:

```julia
size(x)[[2,3]]

```

There are a zillion other possibilities depending on whether `2` and `3` are compile-time constants.

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [March 19, 2021, 6:14pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/8 "2021-03-19T18:14:31Z")

</div>

Let me try to explain, why I think there are compelling reasons for such an addition: I mostly do image processing in multiple dimensions. Each of these dimension typically is attached to a meaning (e.g. XYZ over time and spectral dimension). In my experience in some languages (Matlab, Python) which I used, I am constantly annoyed by the operation such as sub-slicing or reduce operations starting to change the order of dimension. One may want code to run on 2D data or 3D data likewise and the outcome of the processing should depend on the meaning that these dimensions have and not on the fact whether a dimension happens to be singleton or not. In my experience the automatic performance of “squeeze” (`dropdims()`) operations is cause for lots of code clutter and trouble when writing code that is supposed to work for 2D and 3D data alike. In NumPy this can be largely avoided by the ´keepdims=true´ argument of reduce functions. Julia very nicely has this (`keepdims=true`) behaviour as default for reduce operations (sum, maximum, etc.), yet for `selectdim()` singletons are dropped and for sub-indexing you need to specify a range to keep singleton dimensions:

```julia
julia> x=ones(4,5,6);
julia> size(sum(x,dims=2))
(4, 1, 6)
julia> size(x[:,1,:])
(4, 6)
julia> size(x[:,1:1,:])
(4, 1, 6)
julia> size(selectdim(x,2,1))
(4, 6)

```

Adding a tuple as a possible way of calling `size(x, dims)` sounds like a natural and useful addition to me. Depending whether you want this by default to agree to the size you get for `selectdim()` or for reduce operations is in my view a matter of taste, my preference being the latter one. Another useful addition would be to add `keepdims=false` as an optional argument to `selectdim()`.

---

<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:** [March 21, 2021, 10:19am UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/9 "2021-03-21T10:19:42Z")

</div>

Again, I understand that you have a use case for this, but you can just code a function for it if you need it often, or use the solutions above.

Doing transformations in arguments leads to a combinatorial explosion (everyone has a different use case) and is best avoided.

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [March 21, 2021, 11:04am UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/10 "2021-03-21T11:04:38Z")

</div>

Shouldn’t optimizations like that live in some sort of tensor library? It make sense to have some very special multidimensional functions or special versions of functions for multidimensional arrays in corresponding package.

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [March 22, 2021, 12:17pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/11 "2021-03-22T12:17:41Z")

</div>

Good point. Maybe instead of introducing the `keepdims=true` argument, one should use a separate function such as `size_d(x, dims::NTuple)` which returns the size keeping the singleton dimensions and `selectdims_d(x, dims::NTuple)`.  
Where should it live? I think ideally in `AbstractArray`, as I think it may of high general use, but I understand that this may not necessary be the general consensus.

---

<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:** [March 22, 2021, 12:31pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/12 "2021-03-22T12:31:08Z")

</div>

Again, I am wondering if you read @carstenbauer’s [suggestion](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/3) for

```julia
size.(Ref(x),(2,3))

```

It is compact, neat, and requires nothing extra to add to the language.

Here, the secret sauce is [broadcasting](https://docs.julialang.org/en/v1/manual/arrays/#Broadcasting), which is why in Julia you rarely see “vector” and “scalar” versions for the same function.

You can also use

```julia
@. size($x, (2, 3))

```

It does not get any better than this: you get the functionality you need from composing _existing_ building blocks.

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [March 22, 2021, 12:39pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/13 "2021-03-22T12:39:46Z")

</div>

> [@Tamas\_Papp](#):
>
> ```julia
> size.(Ref(x),(2,3))
> 
> ```
> 
> It is compact, neat, and requires nothing extra to add to the language.

If one thinks longer about that, it is indeed nice, but in the first impression, `Ref` felt quite strange to me.  
But if the best method, then it’s probably okay.

However, I believe, the more critical from the part above is:

```julia
julia> size(x,(2,3))
(1, 11, 12)

```

which cannot be written as easy as the other one (can it?)

---

<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:** [March 22, 2021, 12:55pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/14 "2021-03-22T12:55:38Z")

</div>

A lot of things do not have a built-in, but can be easily coded. Eg

```julia
squash′em(x::NTuple{N}, j) where N =
    map((x, i) -> i ∈ j ? x : 1, x, ntuple(identity, Val(N)))
squash′em(size(x), (2, 3))

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [March 22, 2021, 1:01pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/15 "2021-03-22T13:01:51Z")

</div>

> [@roflmaostc](#):
>
> If one thinks longer about that, it is indeed nice, but in the first impression, `Ref` felt quite strange to me.

Yeah, there have been discussion about whether we should have a a function/struct with a better name, like `Scalar` or similar, to indicate that something is a scalar under broadcasting. Maybe it’s worth reactivating the discussion?

PS: I didn’t know about interpolation with `@.`. That’s nice!

> [@Tamas\_Papp](#):
>
> `@. size($x, (2, 3))`

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [March 22, 2021, 4:41pm UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/16 "2021-03-22T16:41:53Z")

</div>

> [@carstenbauer](#):
>
> > [@Tamas\_Papp](#):
> >
> > `@. size($x, (2, 3))`

Is this a new feature? Doesn’t work for me on julia 1.5/6

```julia
julia> A = rand(2,2);

julia> @. size(A, (1,))
2×2 Array{Int64,2}:
 1 1
 1 1

julia> @. size($A, (1,))
2×2 Array{Int64,2}:
 1 1
 1 1

```

---

<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:** [March 23, 2021, 9:29am UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/17 "2021-03-23T09:29:31Z")

</div>

My bad, I forgot that `$` escapes _function calls_, not values.

---

<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:** [March 23, 2021, 10:47am UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/18 "2021-03-23T10:47:03Z")

</div>

There was the idea of adding the syntax `&A` as shorthand for `Ref(A)` (see [#6080](https://github.com/JuliaLang/julia/issues/6080) and [#34693](https://github.com/JuliaLang/julia/issues/34693)). I would love to see this implemented.

@roflmaostc maybe `size.(&x, (2,3))` would look less strange?

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [March 23, 2021, 10:54am UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/19 "2021-03-23T10:54:23Z")

</div>

I believe it feels _strange_ because I cannot associate why a reference would help in broadcasting. For me these terms are not directly connect.  
As @carstenbauer mentioned, `Scalar` would make much more sense (at least for me)

---

<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:** [March 23, 2021, 11:02am UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/20 "2021-03-23T11:02:02Z")

</div>

Agreed… But I thought maybe people would find it easier getting used to `&x` for opting out of broadcasting since it doesn’t put “reference” in your face quite as much as `Ref` 🙂

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 23, 2021, 11:16am UTC](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533/21 "2021-03-23T11:16:30Z")

</div>

> [@roflmaostc](#):
>
> ```julia
> julia> size(x,(2,3))
> (1, 11, 12)
> 
> ```

I must say I would find that very unnatural, for one, that the length of the returned tuple is different from the input tuple, and secondly, that `1` isn’t a ‘special’ enough value to work as a placeholder.

But I also think that `size(x, (2,3))` should be possible, and return the size of those dimensions, it feels more consistent to me. If the preferred solution is `size(x)[[2,3]]`, then `size(x)[2]` should replace `size(x, 2)`. Messing about with `Ref` and broadcasting just seems too awkward.

As a data point, Matlab supports `size(x, [1, 3])`.

[Next page](https://discourse.julialang.org/t/tuple-as-argument-for-size-abstractarray/57533.md?page=2)
