I'm trying to create a simple class that represents a kind of relationship in a simple graph. Relationships are bidirectional and invertable, so if A is "above" B then B must be "below" A.
Supposing I had two instances of Relationship A (Above), and B (Below), that A.invert == B and B.invert == A. To make matters easy, I'd build both A and B from the same factory at the same time.
This is my code so far, obviously wrong:
case class Relationship(name:String, inverse:Relationship=null) {
def setInverse(inverse:Relationship) = {
Relationship(name, inverse)
}
}
val foo = Relationship(name="Foo", Relationship(name="Bar"))
printf(foo.toString) // looks fine
printf(foo.inverse.toString) // null
foo.inverse.inverse = foo // totally wrong!!!
The last line is obviously invalid because it's attempting to mutate something immutable. I saw an approach that might work here, but not with case-classes? Do I have to abandon case classes if I want to make a circular reference?
How can I make two instances of Relationship, each with a property called inverse which is a reference to the other?
Edit 0: Here's my try #2 - not much better
class Relationship(name:String, _inverse:Relationship) {
lazy val inverse = _inverse
}
val foo:Relationship = new Relationship(name="Foo", new Relationship(name="Bar", foo))
printf(foo.toString)
printf(foo.inverse.toString)
When I try this in a scala worksheet I get a java.lang.StackOverflowError, most probably because the sequence foo.inverse.inverse.inverse goes on forever. I've no way of knowing whether I actually constructed an object without preventing this infinite recursion.