Una discusión interesante sobre la distinción entre devoluciones de llamada y continuaciones sobre SO ha provocado esta pregunta. Por definición, una continuación es una representación abstracta de la lógica necesaria para completar un cálculo. En la mayoría de los idiomas, esto se manifiesta como un procedimiento de un argumento al cual se pasa cualquier valor que necesite un procesamiento continuo.
En un lenguaje puramente funcional (donde todas las funciones son ciudadanos puros y de primera clase), creo que una continuación podría modelarse por completo como una función. Así es, después de todo, cómo he entendido previamente las continuaciones hasta este punto. Sin embargo, el mundo está lleno de estado (suspiro ...) y, por lo tanto, la definición general no requiere que se continúe capturando el estado del programa, solo debe abarcar la intención.
Para ayudar a mi comprensión, ¿se puede proporcionar un ejemplo en un lenguaje funcional donde la continuación se exprese de una manera más abstracta que una función? Sé que Scheme le permite tomar la continuación actual de una manera de primera clase (call / cc), pero aun así, parece que el procedimiento de un argumento pasado a call / cc simplemente se le da la continuación actual en forma de otro procedimiento de argumento al que la función call / cc'd puede aplicar su resultado.
Respuestas:
tl; dr; El tipo es la abstracción general sobre una continuación
Una continuación es el tipo de sus entradas y salidas.
Lo más parecido que encontrará a una continuación no basada en el procedimiento es probablemente la mónada de continuación en Haskell, ya que se expresa como un tipo, para lo cual se pueden usar muchas funciones para interactuar con el tipo para interrumpir, reanudar, retroceder, etc.
Puede encapsular ese cierre en un tipo como el
Cont
tipo en Haskell donde obtiene la abstracción de mónada como una "abstracción de nivel superior", y hay otras formas de abstracción sobre las continuaciones que obtiene cuando mira la continuación como un tipo en lugar de simplemente un procedimiento , por ejemploCierre vs. Procedimiento
Al final del día, básicamente tienes razón; una continuación es un "procedimiento", aunque preferiría referirme a él como un cierre. Muchas veces las continuaciones se expresan mejor como cierres de primera clase que han encerrado un entorno limitado. En un lenguaje funcional puro, podría decir que esto no es particularmente razonable porque carece de referencias; Esto es cierto, pero puede encerrar valores y una sola asignación hace que encerrar el valor frente a la referencia sea exactamente lo mismo. Esto da lugar a en Haskell:
Un lenguaje que carece de la capacidad de encerrar un entorno vinculante técnicamente puede carecer de cierres de primera clase, pero incluso entonces hay algún entorno (generalmente el global) que está disponible para el cierre.
Entonces, diría que es más preciso describir una continuación como: Un cierre que se usa de una manera particular.
Conclusión
A la pregunta de "¿Es una continuación implementable de alguna otra manera que no sea un procedimiento?" No. Si no tiene funciones de primera clase , realmente no puede tener continuaciones como tales (sí, los punteros de funciones cuentan como funciones de primera clase, por lo que, alternativamente, puede ser suficiente el acceso arbitrario a la memoria).
Ahora a la pregunta de "¿Hay alguna forma de expresar una continuación de una manera más abstracta que un procedimiento?" Expresarlo como un tipo le brinda una abstracción mucho mayor, permitiéndole tratar la continuación de manera muy general, de modo que pueda interactuar con la continuación de muchas maneras más que simplemente ejecutarla.
fuente
Un ejemplo que te puede gustar son las corutinas. Por ejemplo, las Coroutines de Lua o los iteradores / generadores de Python o C # son similares en potencia a las continuaciones de un solo disparo (continuaciones que solo se le permite llamar una vez), pero la continuación no se convierte explícitamente en una función. En cambio, tiene formas de avanzar la rutina hasta la siguiente declaración de "rendimiento".
Por ejemplo, considere el siguiente programa de Python:
Es similar al siguiente programa Javascript con devoluciones de llamada explícitas:
El ejemplo de Javascript es un poco ruidoso porque cada paso debe devolver la siguiente continuación además de devolver el valor cedido (en Python realiza un seguimiento de la continuación dentro del ite
fuente