# Specifying structs with variably nested NTuple fields

**URL:** <https://discourse.julialang.org/t/specifying-structs-with-variably-nested-ntuple-fields/65817>\
**Category:** General Usage\
**Tags:** struct, ntuple\
**Created:** [August 4, 2021, 2:41pm UTC](https://discourse.julialang.org/t/specifying-structs-with-variably-nested-ntuple-fields/65817 "2021-08-04T14:41:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tchr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tchr/32/15138_2.png) [@tchr](https://discourse.julialang.org/u/tchr)\
**Post date:** [August 4, 2021, 2:41pm UTC](https://discourse.julialang.org/t/specifying-structs-with-variably-nested-ntuple-fields/65817/1 "2021-08-04T14:41:08Z")

</div>

I suspect what I want isn’t possible but wanted to ask here to be certain (or to learn precisely why it isn’t possible).

The setup for the question is as follows. Suppose I have a function:

```nohighlight
function nested_ntuple(::Val{Ns}, ::Type{T}) where {Ns, T}
   if length(Ns) == 1
      return NTuple{first(Ns), T}
   else
      return NTuple{first(Ns), nested_ntuple(Val{Base.tail(Ns)}(), T)}
   end
end

```

which generates nested NTuple types, such that e.g.

```nohighlight
nested_ntuple(Val{(1,2)}(), String) === NTuple{1, NTuple{2, String}}
nested_ntuple(Val{(2,4,3)}(), Float64) === NTuple{2, NTuple{4, NTuple{3, Float64}}}

```

and so on.

What I’m then interested in is specifying a type with variably nested NTuple fields. I.e., conceptually, I’m looking for something like this:

```nohighlight
struct A{Ns, T}
   x::nested_ntuple(Ns, T)
end

```

(Of course, this isn’t a valid signature for specifying a type since we cannot use functions on the type parameters for specifying struct fields - but the point is just to say that it should assign a nested tuple type to `x`).

As context, the reason I am interested in this was to play around with alternatives to e.g. StaticArrays’ use of one long “flat” NTuple for all array data - and the associated “dangling” type parameter `L` - i.e., I wanted to see what the implications are of instead using a nested NTuple approach (in the spirit of [https://github.com/JuliaLang/julia/issues/18466#issuecomment-274353910](https://github.com/JuliaLang/julia/issues/18466#issuecomment-274353910) - and motivated by that entire issue as well).

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 4, 2021, 4:27pm UTC](https://discourse.julialang.org/t/specifying-structs-with-variably-nested-ntuple-fields/65817/2 "2021-08-04T16:27:40Z")

</div>

You could go the easy way:

```julia
julia> struct A{T}
         x::T
       end

julia> A(nested_ntuple(Val{(1,2)}(), String))
A{DataType}(Tuple{Tuple{String, String}})

julia> A((1,(1,2)))
A{Tuple{Int64, Tuple{Int64, Int64}}}((1, (1, 2)))

```

(your function is returning a data type, I’m not sure if that is what is originaly intended).

You could also add type parameters `Ns` and `T` to `A` only for dispatch:

```julia
julia> struct AA{Ns,T,Tup}
         x::Tup
       end

julia> AA{Ns,T}(tup) where {Ns,T} = AA{Ns,T,typeof(tup)}(tup)

julia> AA{2,Int}((1,(1,2)))
AA{2, Int64, Tuple{Int64, Tuple{Int64, Int64}}}((1, (1, 2)))

```

---

<div class="post-metadata">

**Author:** ![tchr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tchr/32/15138_2.png) [@tchr](https://discourse.julialang.org/u/tchr)\
**Post date:** [August 4, 2021, 5:14pm UTC](https://discourse.julialang.org/t/specifying-structs-with-variably-nested-ntuple-fields/65817/3 "2021-08-04T17:14:33Z")

</div>

Hmm, yeah, that is an option, true - hadn’t thought of that - albeit not a very pleasant one :(.  
One of my hopes was to see if it would be possible to simplify the type signature of e.g. `SArray{Size, T, D, L}` to `SArray{Size, T, D}`, i.e. to get rid of extraneous type parameters - which this sort of acts in opposition to.

It was intentional that the `nested_ntuple` is returning a type in this case; otherwise the pseudocode-example for `struct A ...` wouldn’t make sense. Of course, to give the values of `A.x` we’d use an instance of that type.

---

<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:** [August 5, 2021, 12:04pm UTC](https://discourse.julialang.org/t/specifying-structs-with-variably-nested-ntuple-fields/65817/4 "2021-08-05T12:04:02Z")

</div>

> [@tchr](#):
>
> the point is just to say that it should assign a nested tuple type to `x`

Generally you cannot do computations like this on types in a `struct` definition.

The common approach is to leave the type of `x` parametric, and validate in the inner constructor, eg

```julia
using ArgCheck

struct A{Ns,T,S}
    x::S
    function A{Ns,T}(x::S) where {Ns,T,S}
        @argcheck is_nested_ntuple(Val(Ns), Val(T), x) # implement this
        new{Ns,T,S}(x)
    end
end

```

---

<div class="post-metadata">

**Author:** ![tchr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tchr/32/15138_2.png) [@tchr](https://discourse.julialang.org/u/tchr)\
**Post date:** [August 5, 2021, 5:02pm UTC](https://discourse.julialang.org/t/specifying-structs-with-variably-nested-ntuple-fields/65817/5 "2021-08-05T17:02:12Z")

</div>

> [@Tamas\_Papp](#):
>
> > [@tchr](#):
> >
> > the point is just to say that it should assign a nested tuple type to `x`
> 
> Generally you cannot do computations like this on types in a `struct` definition.

I’m not sure I understand? - this was exactly what I wrote in the bit of text you left out from that quote:

> [@tchr](#):
>
> Of course, this isn’t a valid signature for specifying a type since we cannot use functions on the type parameters for specifying struct fields

And also the whole topic of the [issue #18466](https://github.com/JuliaLang/julia/issues/18466) that I linked to?

* * *

> [@Tamas\_Papp](#):
>
> The common approach is to leave the type of `x` parametric, and validate in the inner constructor,

Did you see my previous reply to @lmiq equivalent suggestion? The suggestion is nice, definitely, just not what I was aiming for with this. (Though, I wasn’t aware of ArgCheck; that’s a nice alternative to writing out constructor validations manually - thanks)

* * *

A different way of phrasing my question is whether there’s a non-functional way of expressing a nested `NTuple` type (i.e., in the same sense that `NTuple{N, T}`/`Tuple{Vararg{T, N}}` allows a type-declaration of a definite-length `Tuple{T, T, ...}`).  
It seems there isn’t? - but it’d be cool to learn more about why that is.
