2011-05-29 3 views
16

Me gustaría crear un Iterator que obtiene su siguiente elemento al evaluar (repetidamente) una expresión, y quiero que la expresión pueda devolver un cierto valor para terminarla.¿Cómo crear un iterador finito cuyos contenidos son el resultado de una expresión?

Lo único que he encontrado es Iterator.continually(), que parece ser infinito. Es importante que la expresión no se evalúe hasta que se llame al next() en el Iterator.

¿Hay alguna manera de obtener este comportamiento?

por ejemplo:

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 
+0

¿qué debe devolver el iterador cuando ve el valor de detención? – sourcedelica

+1

no debería devolver más elementos. –

Respuesta

6

¿Has mirado en scala.collection.immutable.Stream? Su propósito es crear una secuencia como objeto donde el siguiente elemento se evalúa perezosamente. Puede ser finito o infinito.

Por ejemplo:

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) 
+3

Creo que esto funciona muy bien cuando se trata de recursividad. De lo contrario, prefiero Iterator, ya que hay ciertas dificultades con Stream, una gran cantidad de datos y referencias de retención a la cabeza de la secuencia. – huynhjl

26

Iterator.continually normalmente se combina con takeWhile:

var count = 0 
def complexCompute(): Int = { count +=1; println("eval " + count); count } 

val iter = Iterator.continually { complexCompute() } 
iter.takeWhile(_ < 3).foreach(println) 

que imprime:

eval 1 
1 
eval 2 
2 
eval 3 

lo tanto, si la condición que determina si el cómputo debe continuar lata ser evaluado fuera del cálculo luego t sus trabajos bastante bien.

Básicamente, supongo que estoy diciendo que Iterator.continually(getNext()).takeWhile(_ != certainValue) logrará lo que estás tratando de hacer. Se evalúa perezosamente.

Cuestiones relacionadas