我试图重写以下示例来自书籍"计算机程序的结构和解释",第3.5.4章: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5.4
以下是我的代码:
def addStream(s1 : Stream[Double], s2 : Stream[Double]) : Stream[Double] = {
(s1.head + s2.head) #:: addStream(s1.tail, s2.tail)
}
def scaleStream(stream : Stream[Double], factor : Double) : Stream[Double] = {
(stream.head * factor) #:: scaleStream(stream.tail, factor)
}
def integral(integrandLazy: => Stream[Double], initialValue : Double, dt : Double) : Stream[Double] = {
def int : Stream[Double] = {
initialValue #:: addStream(scaleStream(evalStream, dt), int)
}
def evalStream : Stream[Double] ={
lazy val stream : Stream[Double] = integrandLazy
stream
}
int
}
def solve(f : Double => Double, y0 : Double, dt : Double) : Stream[Double] = {
def y : Stream[Double] = {
integral(dy, y0, dt)
}
def dy : Stream[Double] = {
y.map(f)
}
y
}
val returnedStream = solve((x : Double) => {x}, 1, 0.001)
val limited = returnedStream take 30
limited foreach println
所以你可以看到我正在尝试使用Scala中的lazy val功能来模拟书中的延迟评估。该程序运行,但在尝试评估流中的第24个元素时会卡住。
我的计划有什么问题?我是否在Scala中使用正确的功能来模拟延迟评估?
答案 0 :(得分:1)
在Scala中,只要您提及,就会对lazy val
进行评估。所以在你的例子中,它并没有完成任何事情,因为你在定义之后就提到了它。
基本上,您可以按照以下方式翻译lazy val
(实际翻译更为复杂,因为它会处理线程问题,但不要在意这里):
def evalStream: Stream[Double] = {
var _stream: Stream[Double] = null
var _streamInit: Boolean = false
def stream: Stream[Double] = {
if (!_streamInit) {
_stream = integrandLazy
_streamInit = true
}
_stream
}
stream
}
从这次改写中,应该清楚的是,整个事情基本上等同于只是急切地评估integrandLazy
。