I accidentally ran into a situation like this (the example is simplified to isolate the problem):
abstract class Element(val other: Element)
case object Fir
The usual way is like this (changed nesting so you can paste it into the REPL):
object Main{
abstract class Element(other0: => Element) {
lazy val other = other0
}
case object First extends Element(Second)
case object Second extends Element(First)
def main(arguments: Array[String]) {
val e1 = First
val e2 = Second
println("e1: "+e1+" e1.other: "+e1.other)
println("e2: "+e2+" e2.other: "+e2.other)
}
}
That is, take a by-name parameter and stick it into a lazy val for future reference.
Edit: The fix you found works because objects are themselves lazy in that you can refer to them but they don't get created until you use them. Thus, one object is free to point itself at the other without requiring that the other one has been initialized already.