Reputation:
I have an infinite Stream and need to "pull" from it until some element, naturally. This is the first step. But only part of the "pulled" elements will be used in the second step, e.g. only the even elements. Is it possible to avoid processing the odd elements by means of lazyness?
The better way to explain what I am asking is showing the code:
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26).
Type in expressions to have them evaluated.
Type :help for more information.
scala> var n=0; def numbers:Stream[Int] = {n += 1; println("n= " + n); n #:: numbers}
n: Int = 0
numbers: Stream[Int]
scala> numbers.map{z => println("z^2= " + z*z) ; z*z}.take(10)(2)
n= 1
z^2= 1
n= 2
z^2= 4
n= 3
z^2= 9
res0: Int = 9
scala> var n=0; def numbers:Stream[Int] = {n += 1; println("n= " + n); n #:: numbers}
n: Int = 0
numbers: Stream[Int]
scala> numbers.map{lazy z => println("z^2= " + z*z) ; z}.take(10)(2)
<console>:1: error: lazy not allowed here. Only vals can be lazy
numbers.map{lazy z => println("z^2= " + z*z) ; z*z}.take(10)(2)
^
scala>
Since the result of take(10)(2)
is res0: Int = 9
, only the z^2= 9
calculation is really needed.
Upvotes: 1
Views: 180
Reputation:
If you want to defer the calculation of z^2
(the map
operation), a view
should suffice:
object Worksheet {
var n = 0 //> n : Int = 0
def numbers: Stream[Int] = { n += 1; println("n= " + n); n #:: numbers }
//> numbers: => Stream[Int]
numbers.view.map { z => println("z^2= " + z * z); z }.take(10)(2)
//> n= 1
//| n= 2
//| n= 3
//| z^2= 9
//| res0: Int = 3
}
If you also want to defer the generation of the numbers in the stream until they are needed, you can do so manually:
object sheet {
var n = 0 //> n : Int = 0
def numbers: Stream[() => Int] = (() => { n += 1; println("n= " + n); n }) #:: numbers
//> numbers: => Stream[() => Int]
numbers.view.map { z => val x = z(); println("z^2= " + x * x); x }.take(10)(2)
//> n= 1
//| z^2= 1
//| res0: Int = 1
}
The issue here seems to be that the streams in the Scala library are not lazy in their head. I wouldn't be surprised if the Scalaz library had something like that already.
Upvotes: 2