It is impossible to make self-referential immutable structures without lazy evaluation. However, lazy evaluation in Scala (represented with lazy vals and call-by-name parameters) is not so pervasive as, say, in Haskell, and it has its limitations. Your code can be rewritten like this:
Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :paste
// Entering paste mode (ctrl-D to finish)
abstract class Person(val name: String)
class Girl(val name2: String, _boyfriend: => Boy) extends Person(name2) {
lazy val boyfriend = _boyfriend
}
class Boy(val name2: String, _girlfriend: => Girl) extends Person(name2) {
lazy val girlfriend = _girlfriend
}
object Run {
val alice: Girl = new Girl("alice", new Boy("Bob", alice))
}
// Exiting paste mode, now interpreting.
defined class Person
defined class Girl
defined class Boy
defined module Run
scala> Run.alice.name
res0: String = alice
scala> Run.alice.boyfriend.name
res1: String = Bob
scala> Run.alice.boyfriend.girlfriend.name
res2: String = alice
scala>
You see, no case classes here - you cannot make case class parameters call-by-name since they are exposed as vals, and it does not make sense for vals to have call-by-name type. Also I had to create additional lazy val field so that call-by-name parameter won't be evaluated too early.
It is possible that this code can be simplified, but it is the simplest way to achieve what you want I can think of.