# How to make mutually referencial structs?

**URL:** <https://discourse.julialang.org/t/how-to-make-mutually-referencial-structs/56952>\
**Category:** General Usage\
**Created:** [March 11, 2021, 2:32pm UTC](https://discourse.julialang.org/t/how-to-make-mutually-referencial-structs/56952 "2021-03-11T14:32:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)\
**Post date:** [March 11, 2021, 2:32pm UTC](https://discourse.julialang.org/t/how-to-make-mutually-referencial-structs/56952/1 "2021-03-11T14:32:32Z")

</div>

Hello, here is a MWE:

```julia
mutable struct Bar{T}
    y::T
    foo
end
Bar(y) = Bar(y, nothing)

mutable struct Foo{T, B <: Bar}
    x::T
    bar::B
end

function Foo(x, bar) 
    foo = Foo(x, bar)
    bar.foo = foo
    return foo
end

bar = Bar(2.)
foo = Foo(10,bar)
bar.foo.x

```

Basically I would like to figure out a way to have two instances, one of each struct, to refer to one another. So, despite the type instability that might ensue, I made Bar with an free typed foo field. When I itinitialize bar, I initialize as nothing and when I instantiate a Foo, it changes the reference of bar.foo from nothing to foo. There’s no error during construction, but the last line returns

```julia
ERROR: type Nothing has no field x
Stacktrace:
 [1] getproperty(::Nothing, ::Symbol) at .\Base.jl:33
 [2] top-level scope at REPL[2]:1

```

So I tried instead to use incomplete initialization

```julia
mutable struct Bar{T}
    y::T
    foo
    Bar(y) = new(y)
end

```

But then I get the error

```julia
ERROR: syntax: too few type parameters specified in "new{...}" around REPL[3]:1
Stacktrace:
 [1] top-level scope at REPL[3]:1

```

I don’t understand, that’s the point of incomplete initialization to have fewer fields…  
Note that I can’t know in advance which type parameters bar.foo will have. In fact, I need bar.foo to be able to accept other structs than Foo.

EDIT: There was a y instead of x but that was not the problem.

---

<div class="post-metadata">

**Author:** ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)\
**Post date:** [March 11, 2021, 2:44pm UTC](https://discourse.julialang.org/t/how-to-make-mutually-referencial-structs/56952/2 "2021-03-11T14:44:17Z")

</div>

So I just found that this might be a scope problem ?  
because when I set (after the first example) in the global scope

```julia
bar.foo = foo
bar.foo.x

```

correctly returns 10.

So it’s the assignment in Foo’s cosntructor that does not do what I expect.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 11, 2021, 2:51pm UTC](https://discourse.julialang.org/t/how-to-make-mutually-referencial-structs/56952/3 "2021-03-11T14:51:50Z")

</div>

As it turns out, the recursive type definitions aren’t actually relevant to the problems you’re having.

First off, this function:

> [@HenriDeh](#):
>
> ```julia
> function Foo(x, bar) 
> foo = Foo(x, bar)
> bar.foo = foo
> return foo
> end
> 
> ```

isn’t working for you because it’s not being called at all. Try this:

```julia
julia> methods(Foo)
# 2 methods for type constructor:
[1] (::Type{Foo})(x::T, bar::B) where {T, B<:Bar} in Main at REPL[3]:2
[2] (::Type{Foo})(x, bar) in Main at REPL[10]:1

```

Method `[1]` is the constructor, which matches any `x` and and `bar::Bar`. Method [2] is the function you wrote, which matches any `x` and any `bar`. So method [2] is _less specific_ and is therefore never actually being called. That’s why it has no effect.

If you make that function more specific (e.g. by making it `Foo(x, bar::Bar)`, then you’re going to run into more problems because on the very next line you do `foo = Foo(x, bar)`. If this function were working _at all_, it would always just call itself immediately, leading to a stack overflow.

This is a classic case where an inner constructor solves the problem:

```julia
julia> mutable struct Foo{T, B <: Bar}
           x::T
           bar::B
           
           function Foo(x::T, bar::B) where {T, B <: Bar}
             foo = new{T, B}(x, bar)
             bar.foo = foo
             return foo
           end
       end

julia> foo = Foo(10, bar)
Foo{Int64,Bar{Float64}}(10, Bar{Float64}(2.0, Foo{Int64,Bar{Float64}}(#= circular reference @-2 =#)))

julia> foo.bar.y
2.0

```

> [@HenriDeh](#):
>
> ```julia
> ERROR: syntax: too few type parameters specified in "new{...}" around REPL[3]:1
> Stacktrace:
> [1] top-level scope at REPL[3]:1
> 
> ```
> 
> I don’t understand, that’s the point of incomplete initialization to have fewer fields…

This isn’t about the incomplete initialization–try it on a simpler case:

```julia
julia> struct Baz{T}
         x::T
         
         Baz(x) = new(x)
       end
ERROR: syntax: too few type parameters specified in "new{...}" around REPL[17]:1  

```

You have to tell `new` what `T` should be, otherwise how does it know what type to construct?

```julia
julia> struct Baz{T}
         x::T
         
         Baz(x::T) where {T} = new{T}(x)
       end

```

By the way, you can also make the `foo` field of `Bar` concrete in your example using an extra type parameter (although it starts to get a bit mind-bending). Here’s a simplified example of two types which contain each other with no type instabilities:

```julia
julia> struct Bar{F}
         foo::F
       end

julia> mutable struct Foo
         bar::Bar{Foo}
         
         function Foo()
           foo = new()
           foo.bar = Bar(foo)
           return foo
         end
       end

julia> foo = Foo()
Foo(Bar{Foo}(Foo(#= circular reference @-2 =#)))

julia> foo.bar
Bar{Foo}(Foo(Bar{Foo}(#= circular reference @-2 =#)))

julia> foo.bar.foo === foo
true

```

---

<div class="post-metadata">

**Author:** ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)\
**Post date:** [March 11, 2021, 2:58pm UTC](https://discourse.julialang.org/t/how-to-make-mutually-referencial-structs/56952/4 "2021-03-11T14:58:29Z")

</div>

Haa yes okay it makes sense now.

Thank for the concrete type example, but that imposes `bar` to be constructed within `Foo`’s constructor, no ?

Thank you though.

---

<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 11, 2021, 3:06pm UTC](https://discourse.julialang.org/t/how-to-make-mutually-referencial-structs/56952/5 "2021-03-11T15:06:31Z")

</div>

[https://stackoverflow.com/a/56418441/1494135](https://stackoverflow.com/a/56418441/1494135)
