2

I am trying to rewrite the following example from the book "Structure and Interpretation of Computer Programs", chapter 3.5.4: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5.4

The following are my codes:

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

So you can see I am trying to use the lazy val feature in Scala to mimic the delayed evaluation in the book. The program runs, but it gets stuck when it tries to evaluate the 24th elements in the stream.

What's wrong with my program? Am I using the right feature in Scala to mimic the delayed evaluation?

mpchau
  • 21
  • 1

1 Answers1

1

In Scala, lazy vals are evaluated as soon as you mention them. So in your example, it doesn't accomplish anything, since you mention it right after you define it.

Essentially, you can translate the lazy val as follows (the actual translation is more involved because it takes care of threading issues, but never mind that here):

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
}

From this rewriting, it should be clear that the whole thing is basically equivalent to just evaluating integrandLazy eagerly.

sjrd
  • 21,805
  • 2
  • 61
  • 91
  • Thanks for your reply! I've used your code but that doesn't solve the problem. The same behavior still persists - it prints the first 24th numbers (around that), and then the program hangs. I tried to step through the program (using IntelliJ here), I do see some strange recursion there. As you also mention about threading issues - maybe it's a mixture of threading/recursion problem invoked by this code? Anyway the codes in my question can be run easily in an object extending App - please try it as well! :) Your help much appreciated! – mpchau Feb 05 '15 at 06:46