# Manipulate types of nested data structure

**URL:** <https://discourse.julialang.org/t/manipulate-types-of-nested-data-structure/24181>\
**Category:** General Usage\
**Created:** [May 13, 2019, 4:30pm UTC](https://discourse.julialang.org/t/manipulate-types-of-nested-data-structure/24181 "2019-05-13T16:30:06Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [May 13, 2019, 4:30pm UTC](https://discourse.julialang.org/t/manipulate-types-of-nested-data-structure/24181/1 "2019-05-13T16:30:06Z")

</div>

I have a type, let’s call it `Special <: Real`, which wraps a vector of length`N`. I have defined methods of most standard functions. Sometimes, however, one or several objects of type `Special` are nested deep into some outer type `Outer` and my usage of `Special` inside `Outer` fails. I would then like to construct one `Outer` for each value in the vector that `Special` wraps.

Say the situation is the following:

```julia
struct Special
    x::Vector{Float64}
end

struct Outer{T}
    a::T
    b::Int
end

a = Outer(Special(randn(3)), 1)

```

More specifically, I would like to create a workspace object `b` which is an identical copy of `a`, except every occurance of an object of type `Special` is replaced by one of the floats inside the vector `Special` wraps. To perform computations on `b` `N` times.

I have looked at [Nested.jl](https://github.com/rafaqz/Nested.jl) and it’s relative [Flatten.jl](https://github.com/rafaqz/Flatten.jl), which allow me to “flatten” a nested structure and later reconstruct it. It’s close to what I need, but I also need to replace occurances of `Special` with `Float64` in the the structure. I can’t really understand if Flatten.jl would allow me to do this or not, it’s implementation is very nontrivial.

Some details:  
`Special` is my type, I have full control over its definition. `Outer` is not mine and I can not control it. I only have access to the object `a` below.  
Preferably, I would like to avoid requiring the user to define any methods to get this to work.

I made an attempt at replacing all occurances of `Special` which works, but it only get’s me half way:

```julia
function build_container(P)
    P isa Special && (return 0.0) # This replaces a Special with a float
    P isa Number && (return P)
    if P isa AbstractArray # Special handling for arrays
        return map(build_container, P)
    end
    fields = map(fieldnames(typeof(P))) do n
        f = getfield(P,n)
        build_container(f)
    end
    fields
end

julia> a = Outer(Special(randn(3)), 1)
Outer{Special}(Special([0.2252388048584368, -1.79643970302527, 0.19512554621122083]), 1)

julia> build_container(a)
(0.0, 1)

julia> a = Outer([Special(randn(3)), Special(randn(3))], 1)
Outer{Array{Special,1}}(Special[Special([0.21367693941408203, -1.3515443961700613, 1.3534416611576705]), Special([-1.0929970912074651, -0.8659938973725613, -1.3585774872551668])], 1)

julia> build_container(a)
([0.0, 0.0], 1)

```

Now this works, but it only gets me halfway there, I need to reconstruct the flattend structure into the appropriate type with `Special` replaced with `Float64`, and here I get lost. Without assuming that `Outer` has a constructor that accepts all fields in order, I can not create it with my “container”.

Any pointers to direct me forward would be greatly appreciated!

---

<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:** [May 13, 2019, 5:04pm UTC](https://discourse.julialang.org/t/manipulate-types-of-nested-data-structure/24181/2 "2019-05-13T17:04:58Z")

</div>

> [@baggepinnen](#):
>
> Without assuming that `Outer` has a constructor that accepts all fields in order, I can not create it with my “container”.

I think this is a design problem that is usually solved by a dedicated interface function, eg not unlike `Base.similar` for arrays.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [May 13, 2019, 5:23pm UTC](https://discourse.julialang.org/t/manipulate-types-of-nested-data-structure/24181/3 "2019-05-13T17:23:19Z")

</div>

Yes the `similar` function would solve the issue very nicely, but having to rely on a `similar` method is somewhat unfortunate, because the type `Outer` is out of my control, and maybe out of the control of the user as well. I could ask the user to specify such a `similar`, but if `Outer` comes from a third-party package the user might not be familiar with it and having to ask the user to write that function is unfortunate. I, as the author of the library containing `Special`, know exactly what is required and just want an automatic way of accomplishing this, preferably with as few ugly hacks as possible 😛
