# How to properly unwrap nested structs to access internals?

**URL:** <https://discourse.julialang.org/t/how-to-properly-unwrap-nested-structs-to-access-internals/35003>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 22, 2020, 1:22am UTC](https://discourse.julialang.org/t/how-to-properly-unwrap-nested-structs-to-access-internals/35003 "2020-02-22T01:22:42Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tlnagy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlnagy/32/5815_2.png) [@tlnagy](https://discourse.julialang.org/u/tlnagy)\
**Post date:** [February 22, 2020, 1:22am UTC](https://discourse.julialang.org/t/how-to-properly-unwrap-nested-structs-to-access-internals/35003/1 "2020-02-22T01:22:42Z")

</div>

Say I have the following architecture:

```julia

struct AArray <: AbstractArray
    arr
end

struct BArray <: AbstractArray
    data::AbstractArray
end

struct CArray <: AbstractArray
    cool_mapping::Dict
end

```

Where I can have `AArray` created the following ways:

```julia
AArray(BArray(CArray))
AArray(CArray)

```

I want to do two things:

1. I want to ensure that `AArray` contains `CArray` either directly in `arr` or wrapped inside of a `BArray`, how can I do this?

2. How can I access `cool_mapping` given an `AArray` regardless of whether it’s wrapped inside of `BArray`?

In reality, I’m trying to wrap an `AxisArray` containing potentially a `ReshapedArray` around a custom Array type or the custom Array type directly.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [February 22, 2020, 6:16am UTC](https://discourse.julialang.org/t/how-to-properly-unwrap-nested-structs-to-access-internals/35003/2 "2020-02-22T06:16:57Z")

</div>

1. Parametric types:

```julia
struct AArray{W<:Union{BArray,CArray}} <: AbstractArray
    arr::W
end

```

1. Multiple dispatch:

```julia
coolmap(a::AArray{CArray}) = a.arr.cool_mapping
coolmap(a::AArray{BArray}) = a.arr.data.cool_mapping

```

---

<div class="post-metadata">

**Author:** ![DrChainsaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drchainsaw/32/8497_2.png) [@DrChainsaw](https://discourse.julialang.org/u/DrChainsaw)\
**Post date:** [February 22, 2020, 1:29pm UTC](https://discourse.julialang.org/t/how-to-properly-unwrap-nested-structs-to-access-internals/35003/3 "2020-02-22T13:29:57Z")

</div>

Another option for 2 is recursion which may be favourable if your real application has alot of combinations:

```julia
coolmap(a::AArray) = coolmap(a.arr)
coolmap(b::BArray) = coolmap(b.data)
coolmap(c::CArray) = c.cool_mapping

```

---

<div class="post-metadata">

**Author:** ![tlnagy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlnagy/32/5815_2.png) [@tlnagy](https://discourse.julialang.org/u/tlnagy)\
**Post date:** [February 22, 2020, 8:06pm UTC](https://discourse.julialang.org/t/how-to-properly-unwrap-nested-structs-to-access-internals/35003/4 "2020-02-22T20:06:52Z")

</div>

> [@Vasily\_Pisarev](#):
>
> 1. Parametric types:
> 
> ```julia
> struct AArray{W<:Union{BArray,CArray}} <: AbstractArray
> arr::W
> end
> 
> ```

Is there a performance penalty for doing the Union like this? I know that there is if I define the following

```julia
struct AArray <: AbstractArray
    arr::Union{BArray, CArray}
end

```

it’s significantly slower, but maybe your solution is less ambiguous to the compiler?

> [@DrChainsaw](#):
>
> Another option for 2 is recursion which may be favourable if your real application has alot of combinations:
> 
> ```julia
> coolmap(a::AArray) = coolmap(a.arr)
> coolmap(b::BArray) = coolmap(b.data)
> coolmap(c::CArray) = c.cool_mapping
> 
> ```

I made a typo in my original post. Type `BArray` is a general type that may or may not have a type `CArray` inside of it so `coolmap` should only be defined for `BArray`s containing `CArray`s, which is different than your answer I believe.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [February 22, 2020, 8:39pm UTC](https://discourse.julialang.org/t/how-to-properly-unwrap-nested-structs-to-access-internals/35003/5 "2020-02-22T20:39:33Z")

</div>

```julia
struct TheStruct{T<:SomeAbstractType}
    x::T
end

```

is _very_ different in performance from

```julia
struct TheStruct
    x::SomeAbstractType
end

```

And that is the whole point with the parametric types.

In the latter case, the type `TheStruct` provides basically no information on what the inner layout of an object is, because one can subtype `SomeAbstractType` with arbitrarily complex type. So, the compiler can only produce slow generic code with unboxing etc.  
In the former case, any concrete object cannot be of type `TheStruct`, it will be of type `TheStruct{SomeType}`. If `SomeType` is a concrete type, then the compiler has information of the data layout from the type of object alone and can produce fast machine code.

Moreover, all types in your OP must be parametric for performance:

```julia
struct CArray{T<:Dict} <: AbstractArray
    cool_mapping::T
end

struct BArray{T<:AbstractArray} <: AbstractArray
    data::T
end

const AllowableATypes = Union{CArray, BArray{<:CArray}}

struct AArray{T<:AllowableATypes} <: AbstractArray
    arr::T
end

```

Note that you can’t have `BArray{CArray}` in `AllowableATypes`, because that would disallow `BArray{CArray{SomeConcreteDictType}}` (cf. `Array{Int}` and `Array{Integer}`). You need a `BArray` parameterized by a type that is a subtype of `CArray`, that’s why a longer signature is required.
