La idea principal de las continuaciones en Scala es la capacidad de interrumpir un programa, guardar su estado de control y reanudarlo en un momento posterior. Las continuaciones aparecen en la web como un concepto que podría ayudar con la programación basada en eventos. Las continuaciones, y en particular las continuaciones delimitadas, son una herramienta de programación versátil. En particular, estamos interesados en su capacidad para suspender y reanudar rutas de código secuenciales de forma controlada sin la sobrecarga sintáctica y sin estar atados a subprocesos de VM.
Así que tratemos de entenderlo con un ejemplo apropiado. Imagine una read()
función que devuelve un byte de la red:
def read: Byte
Esta suele ser la firma de una función síncrona (de bloqueo). Después de todo, tiene un valor de retorno y en lenguajes de programación normales, lo que significa esperar a que ese valor esté disponible. Un programa que lee dos bytes seguidos y los imprime se ve así:
val byte1 = leer
println(“byte1 = ” + byte1)
Val byte2 = leer
println(“byte2 = ” + byte2)
El problema es que en un navegador web o node.js o cualquier otro entorno de un solo subproceso controlado por eventos, esto no es aceptable. simplemente no podemos bloquear durante mucho tiempo, de lo contrario, nada más puede suceder en el sistema.
El problema aquí es que debemos escribir en un estilo divertido, incluso con la sintaxis ligera de Scala para los cierres. Tenga en cuenta también cómo cada devolución de llamada generalmente provoca un nuevo nivel de sangría. Algunos programadores logran acostumbrarse a este estilo, pero no representa el flujo de control de una manera muy natural, y el problema crece con el tamaño del programa.
import scala.util.continuations._
reset {
val byte1 = shift(leer)
println(“byte1 = ” + byte1)
val byte2 = shift(leer)
println(“byte2 = ” + byte2)}
Notamos las construcciones reset y shift. Estos términos no tienen ningún sentido para un recién llegado, pero se introdujeron hace mucho tiempo en un artículo académico, por lo que se reutilizan en Scala. Básicamente, restablecer delimita la continuación. Con continuaciones completas, todo el resto del programa estaría bajo el control de la continuación, pero aquí, lo que sea antes y después del bloque de reinicio no tiene nada que ver con las continuaciones. (Además, restablecer puede devolver un valor, aunque aquí no nos importa).
Entonces, en este ejemplo, sigue las letras de la A a la Z
reset { // A shift { cf: (Int=>Int) => // B val eleven = cf(10) // E println(eleven) val oneHundredOne = cf(100) // H println(oneHundredOne) oneHundredOne } }
Producción:
11 101
En el ejemplo anterior, cuando se llama a una función de continuación cf :
- La ejecución salta el resto del bloque de desplazamiento y comienza de nuevo al final del mismo. el parámetro pasado a cf es lo que el bloque shift «evalúa» a medida que continúa la ejecución. esto puede ser diferente para cada llamada a cf .
- La ejecución continúa hasta el final del bloque de reinicio (o hasta una llamada para reiniciar si no hay bloque). el resultado del bloque de reinicio (o el parámetro para reiniciar() si no hay bloque) es lo que devuelve cf.
- La ejecución continúa después de cf hasta el final del bloque de desplazamiento .
- La ejecución salta hasta el final del bloque de reinicio (¿o una llamada para reiniciar?)
veamos un ejemplo mas:
reset { println("A") shift { k1: (Unit=>Unit) => println("B") k1() println("C") } println("D") shift { k2: (Unit=>Unit) => println("E") k2() println("F") } println("G") }
Producción:
A B D E G F C
Publicación traducida automáticamente
Artículo escrito por Aman_Raj_1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA