# How to deal with recursive type dependencies in immutable structs?

**URL:** https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173
**Category:** New to Julia
**Created:** [January 11, 2021, 6:57pm UTC](https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173 "2021-01-11T18:57:25Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![jeffreyesun](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreyesun/32/13379_2.png) [@jeffreyesun](https://discourse.julialang.org/u/jeffreyesun)
#### Post date: [January 11, 2021, 6:57pm UTC](https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173/1 "2021-01-11T18:57:25Z")

</div>

I want to define structs with a parent-child relationship:

```julia
struct Parent
    children::Vector{Child}
end

struct Child
    parent::Parent
end

```

When I try to execute these definitions, I get:

```julia
ERROR: UnDefVarError: Child not defined

```

The following code, however, runs fine:

```julia
try
    struct Child
        parent::Parent
    end
catch
end

struct Parent
    children::Vector{Child}
end

struct Child
    parent::Parent
end

```

What is the right way to handle this? Can I somehow declare the types before I define them?

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [January 11, 2021, 7:14pm UTC](https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173/2 "2021-01-11T19:14:36Z")

</div>

Here is the relevant issue: [handle mutually-circular type declarations · Issue #269 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/269)  
Bottom line is that it is not resolved yet. The “accepted” solution is to use type-parameters (I think) [https://github.com/JuliaLang/julia/issues/269#issuecomment-68421745](https://github.com/JuliaLang/julia/issues/269#issuecomment-68421745)

I haven’t come across your trick with `try` yet. It sure seems to work, the top example from 269 is:

```julia
julia> try 
           struct Foo
           a::Bar
           Foo() = new()
           Foo(a) = new(a)
       end
       catch
       end
       
    struct Bar
           b::Foo
           Bar() = new()
           Bar(b) = new(b)
    end

julia> struct Foo
           a::Bar
           Foo() = new()
           Foo(a) = new(a)
       end

julia> Foo(Bar(Foo()))
Foo(Bar(Foo(#undef)))

```

---

<div class="post-metadata">

### Author: ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)
#### Post date: [January 11, 2021, 7:15pm UTC](https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173/3 "2021-01-11T19:15:37Z")

</div>

I have used [parametric types](https://docs.julialang.org/en/v1/manual/types/#Parametric-Types) to solve this in the past:

```julia
struct Parent{T}
    children::Vector{T}
end

struct Child
    parent::Parent{Child}
end

p = Parent{Child}(Vector{Child}[])

push!(p.children, Child(p))

```

---

<div class="post-metadata">

### Author: ![jeffreyesun](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreyesun/32/13379_2.png) [@jeffreyesun](https://discourse.julialang.org/u/jeffreyesun)
#### Post date: [January 11, 2021, 7:20pm UTC](https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173/4 "2021-01-11T19:20:27Z")

</div>

Thanks! Weird gap in the language, though. It would be nice if something like this worked:

```julia
type Foo

struct Bar
    b::Foo
end

struct Foo
    b::Bar
end

```

I suppose you could do

```julia
macro type(t)
    quote
        try
            struct $t
                a::NotARealType
            end
        catch; end
    end
end
```

---

<div class="post-metadata">

### Author: ![jeffreyesun](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreyesun/32/13379_2.png) [@jeffreyesun](https://discourse.julialang.org/u/jeffreyesun)
#### Post date: [January 12, 2021, 9:27pm UTC](https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173/5 "2021-01-12T21:27:11Z")

</div>

It occurs to me that you could also define a single-child supertype, which I don’t _think_ would affect performance:

```julia
abstract type SuperFoo
struct Bar
    b::SuperFoo
end

struct Foo <: SuperFoo
    b::Bar
end

```

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [January 12, 2021, 9:52pm UTC](https://discourse.julialang.org/t/how-to-deal-with-recursive-type-dependencies-in-immutable-structs/53173/6 "2021-01-12T21:52:42Z")

</div>

Having a non-concrete field in a `struct` is indeed bad for performance. However, you could do

```julia
abstract type SuperFoo end
struct Bar{T <: SuperFoo}
    b::T
end

struct Foo <: SuperFoo
    b::Bar
end

```
