# Structs calling each other

**URL:** <https://discourse.julialang.org/t/structs-calling-each-other/119921>\
**Category:** General Usage\
**Tags:** struct\
**Created:** [September 26, 2024, 1:40pm UTC](https://discourse.julialang.org/t/structs-calling-each-other/119921 "2024-09-26T13:40:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nichola](https://avatars.discourse-cdn.com/v4/letter/n/f0a364/32.png) [@Nichola](https://discourse.julialang.org/u/Nichola)\
**Post date:** [September 26, 2024, 1:40pm UTC](https://discourse.julialang.org/t/structs-calling-each-other/119921/1 "2024-09-26T13:40:56Z")

</div>

I would like to define two structs `AB` and `BA` and be able to convert from one representation to the other doing `AB(ba)` or `BA(ab)` where `ab` and `ba` are instances of `AB` and `BA` respectively.

for example :

```julia
mutable struct AB
    a::Int
    b::Int
    function AB(a::Int, b::Int)
        new(a, b)
    end
    function AB(ba::BA) # convert from BA
        new(ba.b, ba.a)
    end
end

mutable struct BA
    a::Int
    b::Int
    function BA(ab::AB) # convert from AB
        new(ab.b, ab.a)
    end
end

```

But I cannot do that because `BA` is not yet defined when `AB` is being defined.  
Can I just add a function outside of the structs that does

```julia
function AB(ba::BA)
    return AB(ba.b, ba.a)
end

```

?  
Then is it a problem that `AB` is both a type and a function ?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [September 26, 2024, 1:49pm UTC](https://discourse.julialang.org/t/structs-calling-each-other/119921/2 "2024-09-26T13:49:06Z")

</div>

Functions like that are fine, when you use constructors inside struct definitions they have the special ability to define the actual struct with `new(...)` which is the “actual” constructor and will not dispatch to any other thing. So inner constructors can be nice as a guard to disallow construction of a struct without some conditions on the fields being met. You cannot do that as well with outer constructors because you have to call the inner constructor in them, so at that point your checks might not hold anymore.

[https://docs.julialang.org/en/v1/manual/constructors/](https://docs.julialang.org/en/v1/manual/constructors/)

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [September 26, 2024, 3:29pm UTC](https://discourse.julialang.org/t/structs-calling-each-other/119921/3 "2024-09-26T15:29:00Z")

</div>

To be clear, if you moved your “converting” constructors outside of the `struct` block (and replaced `new` with a call to a constructor) so that they became normal functions, you’d get what you want.

E.g.,

```julia
AB(ba::BA) = AB(ba.a, ba.b)
BA(ab::AB) = BA(ab.b, ab.a)

```

Also, your inner constructor

```julia
    function AB(a::Int, b::Int)
        new(a, b)
    end

```

is basically a duplicate of the default constructor except that it’s less flexible (defining any inner constructor prevents a default constructor from being defined). I would delete it. [Inner constructors](https://docs.julialang.org/en/v1/manual/constructors/#man-inner-constructor-methods) (functions defined _inside_ a `struct` block) are only needed in some special cases. For example, you could use an inner constructor to require that any constructed instance satisfies `a < b`.
