recorrer programacion lista introduccion funciones funcional ejemplos codigos codigo scala yield continue yield-return yield-keyword

programacion - ¿Es posible usar ''rendimiento'' para generar ''Iterador'' en lugar de una lista en Scala?



scala ejemplos (3)

¿Es posible usar el rendimiento como un iterador sin evaluar cada valor?

Es una tarea común cuando es fácil implementar la generación de listas complejas, y luego necesita convertirla en Iterator , porque no necesita algunos resultados ...


Por supuesto. En realidad, hay tres opciones de no rigidez, que enumero a continuación. Para los ejemplos, asuma:

val list = List.range(1, 10) def compute(n: Int) = { println("Computing "+n) n * 2 }

  1. Stream Una Stream es una lista perezosamente evaluada. Calculará los valores a pedido, pero no volverá a calcular los valores una vez que se hayan calculado. Es más útil si reutilizará partes de la secuencia muchas veces. Por ejemplo, al ejecutar el código siguiente se imprimirá "Computing 1", "Computing 2" y "Computing 3", una vez cada uno.

    val stream = for (n <- list.toStream) yield compute(n) val third = stream(2) println("%d %d" format (third, stream(2)))

  2. Una vista Una vista es una composición de operaciones sobre una colección base. Al examinar una vista, cada elemento examinado se calcula a pedido. Es más útil si accede a la vista de forma aleatoria, pero nunca verá sino una pequeña parte de ella. Por ejemplo, ejecutar el código siguiente imprimirá "Computing 3" dos veces, y nada más (bueno, además del resultado).

    val view = for (n <- list.view) yield compute(n) val third = view(2) println("%d %d" format (third, view(2)))

  3. Iterator Un Iterator es algo que se utiliza para caminar perezosamente a través de una colección. Uno puede pensar que es una colección "de un solo disparo", por así decirlo. No recompensará ni almacenará ningún elemento; una vez que se ha "computado" un elemento, no se puede volver a utilizar. Es un poco más difícil de usar debido a eso, pero es la más eficiente dadas estas restricciones. Por ejemplo, el siguiente ejemplo debe ser diferente, ya que Iterator no admite el acceso indexado (y la vista funcionaría mal si se escribiera de esta manera), y el siguiente código imprime "Computing 1", "Computing 2", "Computing 3", "Computing 4", "Computing 5" y "Computing 6". Además, imprime dos números diferentes al final.

    val iterator = for (n <- list.iterator) yield compute(n) val third = iterator.drop(2).next println("%d %d" format (third, iterator.drop(2).next))


Tengo una List ...

scala> List(1, 2, 3) res0: List[Int] = List(1, 2, 3)

Y una función ...

scala> def foo(i : Int) : String = { println("Eval: " + i); i.toString + "Foo" } foo: (i: Int)String

Y ahora usaré una comprensión para un Iterator ...

scala> for { i <- res0.iterator } yield foo(i) res2: Iterator[java.lang.String] = non-empty iterator

Puede usar un para la comprensión de cualquier tipo con flatMap , map y métodos de filter . También puedes usar las vistas :

scala> for { i <- res0.view } yield foo(i) res3: scala.collection.SeqView[String,Seq[_]] = SeqViewM(...)

La evaluación no es estricta en ningún caso ...

scala> res3.head Eval: 1 res4: String = 1Foo