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 :
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
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 ?
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.
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.
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 (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.