# Proper use of recursive fields in structs / types

**URL:** <https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611>\
**Category:** New to Julia\
**Created:** [September 22, 2022, 1:31am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611 "2022-09-22T01:31:52Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ivoytov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivoytov/32/42480_2.png) [@ivoytov](https://discourse.julialang.org/u/ivoytov)\
**Post date:** [September 22, 2022, 1:31am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/1 "2022-09-22T01:31:52Z")

</div>

I am writing my first module and have several data structures that will be all linked to each other, sort of like blog posts and comments. I have a file for each data structure that will house methods relevant to each. The following code doesn’t work as the compiler doesn’t know what a `Comment` data type is when it parses the `Post` struct.

_File `Blog.jl`_

```julia
module Blog
include("post.jl")
include("comment.jl")
end

```

_File `post.jl`_

```julia
struct Post
    comments::Vector{Comment}
end

```

_File `comment.jl`_

```julia
struct Comment
    post::Post
end

```

Since the `include` command is a simple copy paster, adding include statements in every file doesn’t work either, as it creates an infinite loop.

What is the recommended way of doing this?

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [September 22, 2022, 1:51am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/2 "2022-09-22T01:51:29Z")

</div>

It seems to me that the problem is the definition of the types.  
There is no place to stop when interpreting the types: it is recursive all the way down to the turtles.

---

<div class="post-metadata">

**Author:** ![ivoytov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivoytov/32/42480_2.png) [@ivoytov](https://discourse.julialang.org/u/ivoytov)\
**Post date:** [September 22, 2022, 2:05am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/3 "2022-09-22T02:05:26Z")

</div>

So what is the most effective way of implementing this design pattern in Julia? I’ve played around a bit and here is what I found:

_Undef: Post not defined_

```julia
struct Comment
    post::Post
end

struct Post
    comments::Vector{Comment}
end

```

but if you use generics, then it works

```julia
struct Post{C <: Vector}
    comments::C
end

struct Comment
    post::Post
end

```

I’ve even thought of a completely different design pattern like this:

```julia
struct Post
   author_id::Int
   text::String
end

struct Comment
   user_id::Int
   text::String
end

struct PostComments
   post::Post
   comments::Vector{Comment}
end

```

Perhaps this is the preferred way to implement this? But it would be so inefficient without any way of being able to query the parent post like so `my_comment.post`.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [September 22, 2022, 2:32am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/4 "2022-09-22T02:32:25Z")

</div>

So you want the comments to contain references to posts, not necessarily the post themselves. Correct?

---

<div class="post-metadata">

**Author:** ![ivoytov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivoytov/32/42480_2.png) [@ivoytov](https://discourse.julialang.org/u/ivoytov)\
**Post date:** [September 22, 2022, 2:33am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/5 "2022-09-22T02:33:31Z")

</div>

that’s correct, I want a pointer to the Post object (not a duplicate)

I also found [this answer](https://stackoverflow.com/questions/56417749/julia-circular-reference) on SO from 2019 that seems to cover this exact question.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [September 22, 2022, 5:05am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/6 "2022-09-22T05:05:52Z")

</div>

```julia
abstract type AbstractComment end
abstract type AbstractPost end

struct Comment{P <: AbstractPost} <: AbstractComment
    post::P
end

struct Post{C <: AbstractComment} <: AbstractPost
    comments::Vector{C}
end

```

---

<div class="post-metadata">

**Author:** ![ivoytov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivoytov/32/42480_2.png) [@ivoytov](https://discourse.julialang.org/u/ivoytov)\
**Post date:** [September 22, 2022, 9:22am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/7 "2022-09-22T09:22:06Z")

</div>

Thanks. Can you remove the use of abstract comment and use the actual `Comment` type since it gets defined first? Compiler only needed one of them in my test.

And tangential question - where do I instantiate the empty `Comment[]` array? Pass it to the default constructor? I wasn’t able to do something Iike `C[]` in an inner constructor.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [September 23, 2022, 7:57am UTC](https://discourse.julialang.org/t/proper-use-of-recursive-fields-in-structs-types/87611/8 "2022-09-23T07:57:09Z")

</div>

> [@ivoytov](#):
>
> And tangential question - where do I instantiate the empty `Comment[]` array? Pass it to the default constructor? I wasn’t able to do something Iike `C[]` in an inner constructor.

```julia
julia> abstract type AbstractComment end

julia> abstract type AbstractPost end

julia> struct Comment{P <: AbstractPost} <: AbstractComment
           post::P
       end

julia> struct Post{C <: AbstractComment} <: AbstractPost
           comments::Vector{C}
           Post(comments::Vector{C} = Comment[]) where C <: AbstractComment = new{C}(comments)
       end

julia> Post()
Post{Comment}(Comment[])

julia> Post(AbstractComment[])
Post{AbstractComment}(AbstractComment[])

```

> [@ivoytov](#):
>
> Thanks. Can you remove the use of abstract comment and use the actual `Comment` type since it gets defined first? Compiler only needed one of them in my test.

Yes, but now we’re not following the design pattern.

```julia
abstract type AbstractPost end

struct Comment{P <: AbstractPost}
    post::P
end

struct Post<: AbstractPost
   comments::Vector{Comment}
end
Post() = Post(Comment[])

```
