如果没有惰性求值,就不可能制作自引用的不可变结构。然而,Scala 中的惰性求值(以惰性 val 和按名称调用的参数表示)并不像 Haskell 中那样普遍,并且它有其局限性。您的代码可以这样重写:
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>
你看,这里没有案例类——你不能让案例类参数按名称调用,因为它们作为 val 公开,并且 val 具有按名称调用类型是没有意义的。此外,我还必须创建额外的惰性 val 字段,以便不会过早评估按名称调用的参数。
这段代码有可能可以简化,但这是我能想到的实现你想要的最简单的方法。