How to create a finite iterator with contents being a result of an expression?
I'd like to create an Iterator
that gets its next element by (repeatedly) evaluating an expression, and I want the expression to be able to return a certain value to terminate it.
The only thing I've found like this is Iterator.continually(), which seems to be infinite. It's important that the expression should not be evaluated until next()
开发者_如何学JAVAis called on the Iterator
.
Is there a way to get this behaviour?
for example:
def getNext = {
// some complicated code
val next = ... // either a STOP value or a real value to be returned by the iterator
}
val myIter = Iterator.continually(getNext) // want this to stop at some point
Iterator.continually
is usually combined with takeWhile
:
var count = 0
def complexCompute(): Int = { count +=1; println("eval " + count); count }
val iter = Iterator.continually { complexCompute() }
iter.takeWhile(_ < 3).foreach(println)
Which prints:
eval 1
1
eval 2
2
eval 3
So if the condition that determines whether the computation should continue can be evaluated outside the computation then this works pretty well.
Basically I guess I'm saying Iterator.continually(getNext()).takeWhile(_ != certainValue)
will achieve what you're trying to do. It's lazily evaluated.
Have you looked at scala.collection.immutable.Stream? It's purpose it to create a sequence like object where the next element is lazily evaluated. It can be finite or infinite.
For example:
Welcome to Scala version 2.9.0.final (Java HotSpot(TM) Client VM, Java 1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import collection.immutable._
import collection.immutable._
scala> def next(i: Int): Stream[Int] = Stream.cons(i*i, next(i*i))
next: (i: Int)scala.collection.immutable.Stream[Int]
scala> val stream = next(2)
stream: scala.collection.immutable.Stream[Int] = Stream(4, ?)
scala> stream.find(_ > 1000)
res0: Option[Int] = Some(65536)
精彩评论