这是我的尝试:
case class A(val a: A, val b: Int){
override def toString() = b.toString
}
lazy val x: A = A(y, 0)
lazy val y: A = A(z, 1)
lazy val z: A = A(x, 2)
尝试用x做任何事情时出现问题;导致x被评估的开始是通过x,y,z的循环评估,并以堆栈溢出结束。有没有办法指定应该懒惰地计算val?
答案 0 :(得分:8)
您可以像这样使用Stream
:
lazy val stream: Stream[Int] = 0 #:: 1 #:: 2 #:: stream
stream.take(10).toList
// List(0, 1, 2, 0, 1, 2, 0, 1, 2, 0)
通常,您应该使用call-by-name
参数:
class A(_a: => A, val b: Int) {
lazy val a = _a
override def toString() = s"A($b)"
}
用法:
scala> :paste
// Entering paste mode (ctrl-D to finish)
lazy val x: A = new A(y, 0)
lazy val y: A = new A(z, 1)
lazy val z: A = new A(x, 2)
// Exiting paste mode, now interpreting.
x: A = <lazy>
y: A = <lazy>
z: A = <lazy>
scala> z.a.a.a.a.a
res0: A = A(1)
答案 1 :(得分:3)
您可以使用Stream
数据类型定义惰性循环列表:
lazy val circular: Stream[Int] = 1 #:: 2 #:: 3 #:: circular
您可以使用名称参数自行执行相同的操作:
class A(head: Int, tail: => A)
lazy val x = new A(0, y)
lazy val y = new A(1, z)
lazy val z = new A(2, x)
请注意,这不适用于 case 类。
答案 2 :(得分:3)
你需要让A.a
本身懒惰。
您可以通过将其转换为用于初始化惰性字段的名称参数来执行此操作:
class A(a0: => A, val b: Int){
lazy val a = a0
override def toString() = b.toString
}
object A {
def apply( a0: => A, b: Int ) = new A( a0, b )
}
您也可以使用帮助程序类Lazy
执行相同的操作:
implicit class Lazy[T]( getValue: => T ) extends Proxy {
def apply(): T = value
lazy val value = getValue
def self = value
}
除了将a: A
更改为a: Lazy[A]
之外,您的代码几乎没有变化:
case class A(val a: Lazy[A], val b: Int){
override def toString() = b.toString
}
请注意,要访问Lazy
中包含的实际值,您可以使用apply
或value
(如x.a()
或x.a.value
)
答案 3 :(得分:2)
您可以使用按名称参数。
class A(__a: => A, val b: Int) {
def a = __a
override def toString() = b.toString
}
object A {
def apply(a: => A, b: Int) = new A(a, b)
}