#scala
#scala
Вопрос:
Я хотел бы создать Iterator
, который получает свой следующий элемент путем (многократного) вычисления выражения, и я хочу, чтобы выражение могло возвращать определенное значение для его завершения.
Единственное, что я нашел подобное, — это A):Iterator[A]» rel=»noreferrer»>Iterator.continuously(), который кажется бесконечным. Важно, чтобы выражение не вычислялось до 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. что должен возвращать итератор, когда он видит значение stop?
2. он не должен возвращать больше никаких элементов.
Ответ №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.Поток? Это предназначено для создания объекта, подобного последовательности, где следующий элемент вычисляется лениво. Оно может быть конечным или бесконечным.
Например:
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)
Комментарии:
1. Я думаю, что это действительно хорошо работает, когда задействована рекурсия. В противном случае я предпочитаю итератор, поскольку есть определенные подводные камни с потоком, большим количеством данных и сохранением ссылок на начало потока.