¿Cómo puede uno poner en práctica usando C# yield return
continuaciones Scala? Me gustaría poder escribir Scala Iterator
s en el mismo estilo. Una puñalada está en los comentarios en this Scala news post, pero no funciona (intenté utilizar la versión beta de Scala 2.8.0). Las respuestas en un related question sugieren que esto es posible, pero aunque he estado jugando con continuaciones delimitadas por un tiempo, parece que no puedo entender exactamente cómo hacerlo.rendimiento de ejecución (retorno de rendimiento) usando Scala continuaciones
Respuesta
Antes de presentar las continuaciones que se necesita construir algunas infraestructuras. A continuación se muestra un trampoline que opera en los objetos Iteration
. Una iteración es un cálculo que pueden o bien Yield
un nuevo valor o puede ser Done
.
sealed trait Iteration[+R]
case class Yield[+R](result: R, next:() => Iteration[R]) extends Iteration[R]
case object Done extends Iteration[Nothing]
def trampoline[R](body: => Iteration[R]): Iterator[R] = {
def loop(thunk:() => Iteration[R]): Stream[R] = {
thunk.apply match {
case Yield(result, next) => Stream.cons(result, loop(next))
case Done => Stream.empty
}
}
loop(() => body).iterator
}
La cama elástica utiliza un bucle interno que convierte la secuencia de Iteration
objetos en un Stream
. A continuación, obtener una Iterator
llamando iterator
en el objeto de flujo resultante. Al usar un Stream
, nuestra evaluación es floja; no evaluamos nuestra próxima iteración hasta que se necesite.
La cama elástica puede ser utilizado para construir un iterador directamente.
val itr1 = trampoline {
Yield(1,() => Yield(2,() => Yield(3,() => Done)))
}
for (i <- itr1) { println(i) }
Eso es bastante horrible para escribir, por lo que vamos a utilizar continuaciones delimitados para crear nuestros objetos Iteration
automáticamente.
usamos el shift
y reset
operadores para romper el cálculo arriba en Iteration
s, a continuación, utilizar trampoline
para convertir los Iteration
s en un Iterator
.
import scala.continuations._
import scala.continuations.ControlContext.{shift,reset}
def iterator[R](body: => Unit @cps[Iteration[R],Iteration[R]]): Iterator[R] =
trampoline {
reset[Iteration[R],Iteration[R]] { body ; Done }
}
def yld[R](result: R): Unit @cps[Iteration[R],Iteration[R]] =
shift((k: Unit => Iteration[R]) => Yield(result,() => k(())))
Ahora podemos reescribir nuestro ejemplo.
val itr2 = iterator[Int] {
yld(1)
yld(2)
yld(3)
}
for (i <- itr2) { println(i) }
Mucho mejor!
Ahora aquí hay un ejemplo del C# reference page para yield
que muestra un uso más avanzado. Los tipos pueden ser un poco difíciles de acostumbrar, pero todo funciona.
def power(number: Int, exponent: Int): Iterator[Int] = iterator[Int] {
def loop(result: Int, counter: Int): Unit @cps[Iteration[Int],Iteration[Int]] = {
if (counter < exponent) {
yld(result)
loop(result * number, counter + 1)
}
}
loop(number, 0)
}
for (i <- power(2, 8)) { println(i) }
me gustaría ver el salida de scalac -print para iterator, yld, y la asignación a itr2. ¿Podría alguien con el complemento agregar esto a la respuesta? – retronym
Solo intentaba aplicar esto, así que tenía el código en funcionamiento. Vea http://gist.github.com/297230 para la salida (vaya al final). – huynhjl
Cambiaría el nombre de 'iterator' a' yldIterator' o algo así, para evitar confusiones. :-) –
Me las arreglé para descubrir una manera de hacerlo, después de unas horas más de juego. Pensé que era más fácil de entender que todas las otras soluciones que he visto hasta ahora, aunque después aprecié mucho las soluciones de Rich y Miles'.
def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit @suspendable = {
if (cond) {
body
loopWhile(cond)(body)
}
}
class Gen {
var prodCont: Unit => Unit = { x: Unit => prod }
var nextVal = 0
def yld(i: Int) = shift { k: (Unit => Unit) => nextVal = i; prodCont = k }
def next = { prodCont(); nextVal }
def prod = {
reset {
// following is generator logic; can be refactored out generically
var i = 0
i += 1
yld(i)
i += 1
yld(i)
// scala continuations plugin can't handle while loops, so need own construct
loopWhile (true) {
i += 1
yld(i)
}
}
}
}
val it = new Gen
println(it.next)
println(it.next)
println(it.next)
¿Las continuaciones de Scala no pueden manejar while loops? ¡Ay! –
De hecho. :(Esperemos que se trate de un trabajo en progreso, pero creo que las comprensiones definitivamente no son compatibles con el cambio, ya que eso implicaría desmantelar el mapa/foreach/etc. – Yang
Ya no más. Llamar al código cps desde dentro loop es posible desde hace un tiempo. Sin embargo, las comprensiones aún no son compatibles (realmente no creo que ganen soporte nunca) –
- 1. scala - sintaxis de rendimiento
- 2. Diferentes resultados de rendimiento vs retorno
- 3. patrón de trabajo de rendimiento rendimiento
- 4. erlang vs jvm (scala) rendimiento de recursión
- 5. ¿Qué es el rendimiento de Scala?
- 6. Rendimiento de rendimiento dentro de los usos
- 7. Rendimiento de rendimiento en Java
- 8. Rendimiento del bucle de retorno de Linux con TCP_NODELAY habilitado
- 9. Operaciones de Scala con rendimiento de matrices (complemento scalacl)
- 10. Alto rendimiento Concurrent MultiMap Java/Scala
- 11. Scala Rendimiento: estilo imperativo vs funcional
- 12. Rendimiento de rendimiento del rendimiento: en Smalltalk (específicamente Squeak)
- 13. rendimiento rendimiento muchos?
- 14. ¿El retorno de rendimiento en C# es seguro para subprocesos?
- 15. aplicación Scala de C# -como rendimiento con "para"
- 16. Prueba automática de rendimiento de las bibliotecas de Scala
- 17. ¿Qué tipo de hormigón devuelve 'rendimiento rendimiento'?
- 18. rendimiento de rendimiento anidado con IEnumerable
- 19. Rendimiento en tiempo de ejecución de reflexión de Java
- 20. Event Store 3.0 - Rendimiento/rendimiento
- 21. Comportamiento de rendimiento extraño
- 22. Uso sobrecargado del rendimiento rendimiento
- 23. Rendimiento de dynamic_cast?
- 24. Rendimiento de GCC
- 25. rendimiento lento de SqlDataReader
- 26. boost :: función de rendimiento en tiempo de ejecución
- 27. implementación de declaración de rendimiento
- 28. Scala Tipo de retorno
- 29. ¿Cómo habilito las continuaciones en Scala?
- 30. Rendimiento de Scala XML frente a Java XML
Lo que no funciona de ese ejemplo? No compila, o no produce los resultados esperados? Se menciona que, para que funcione, podría ser necesario tener un "foreach" consciente de CPS, pero, en cualquier caso, sería útil saber cuál es el problema. –
No compila. – Yang
Es posible que desee comprobar la respuesta de Miles Sabin a una pregunta similar que tuve http://stackoverflow.com/questions/2137619/scala-equivalent-to-python-generators/2146456#2146456. No estoy seguro de que eso te acerque más. – huynhjl