Как создать конечный итератор с содержимым, являющимся результатом выражения?
Я хотел бы создать Iterator
, который получает свой следующий элемент (неоднократно), оценивая выражение, и я хочу, чтобы выражение могло возвращать определенное значение для его завершения.
Единственное, что я нашел, это Iterator.continually(), который кажется бесконечным. Важно, чтобы выражение не оценивалось до тех пор, пока next()
не будет вызвано на Iterator
.
Есть ли способ получить это поведение?
например:
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
Ответы
Ответ 1
Iterator.continually
обычно сочетается с takeWhile
:
var count = 0
def complexCompute(): Int = { count +=1; println("eval " + count); count }
val iter = Iterator.continually { complexCompute() }
iter.takeWhile(_ < 3).foreach(println)
Какие принты:
eval 1
1
eval 2
2
eval 3
Итак, если условие, которое определяет, следует ли продолжить вычисление, может быть оценено вне вычислений, тогда это работает очень хорошо.
В принципе, я думаю, что я говорю, что Iterator.continually(getNext()).takeWhile(_ != certainValue)
достигнет того, что вы пытаетесь сделать. Он лениво оценил.
Ответ 2
Вы посмотрели scala.collection.immutable.Stream? Он предназначен для создания последовательности, подобной объекту, где лениво оценивается следующий элемент. Он может быть конечным или бесконечным.
Например:
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)