Как создать конечный итератор с содержимым, являющимся результатом выражения?

#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. Я думаю, что это действительно хорошо работает, когда задействована рекурсия. В противном случае я предпочитаю итератор, поскольку есть определенные подводные камни с потоком, большим количеством данных и сохранением ссылок на начало потока.