¿Puede la llamada / cc de Scheme implementar todas las estructuras de flujo de control conocidas?

13

La página "Esquema avanzado: algunos bits traviesos" dice:

Las continuaciones son una construcción poderosa de flujo de control de la cual se puede derivar casi cualquier otra estructura de flujo de control.

¿Pensé que Scheme call/cc, al estar relacionado (*) con el operador J de Peter Landin, podría usarse para implementar cualquier estructura de flujo de control conocida?

Con la "estructura de flujo de control", estoy pensando específicamente en la descripción que hace Wikipedia de ellos, por ejemplo, excepciones, corutinas, hilos verdes, etc.

Específicamente, ¿hay ejemplos de estructuras de flujo de control que no se puedan implementar usando call/cc?

(*) No he podido desenterrar ningún documento que establezca que call/ccsea ​​tan poderoso como el operador J. Un artículo de Felleisen (que no he leído y ciertamente tengo problemas para entenderlo completamente) investiga esto, y parece concluir que a pesar de que están en diferentes clases de complejidad, son formalmente equivalentes.

(También tenga en cuenta que he actualizado la pregunta basada en los comentarios a continuación)

Actualizar

Basado en la excelente respuesta de @Neel a continuación, he mirado sitios que comentan sobre continuaciones delimitadas y no delimitadas , y de hecho parece que call/cc, si bien no está delimitado, no es suficiente. Mientras tanto, parece que se pueden usar continuaciones delimitadas de primera clase (como shift/reset) para expresar cualquier estructura de flujo de control.

csl
fuente
55
¿Cuál es la definición formal de una "estructura de flujo de control"?
Huck Bennett
44
Re: continuaciones no delimitadas. ¿Leíste el artículo referenciado por Hayo Thielecke? El reclamo real es que las continuaciones no delimitadas según lo dispuesto porcall/cc no pueden expresar excepciones en ausencia de estado . (Como Thielecke va a señalar, las excepciones pueden ser implementadas por los que pasa alrededor de dos continuaciones, una para el programa y el otro para el manejador de excepciones, sino que requiere algo más que simplemente call/cc.)
RICI
@Rici: solo hojeé las primeras páginas. (Leer documentos me lleva mucho tiempo). ¡Gracias por el comentario!
csl
@HuckBennett No tengo una definición formal, pero informalmente me refiero a lo que describió en en.wikipedia.org/wiki/Control_flow , específicamente me refiero a que puedes usar continuaciones para expresar y, lo que es más importante, implementar, rutinas, hilos verdes, excepciones, declaraciones de escape, el amboperador, etc.
csl
2
@csl Además de hacer más preciso lo que significa "estructura de flujo de control", también debe ser más claro lo que significa "expresar" algo. Este es un problema difícil, y la respuesta a su pregunta depende en gran medida de lo que cuente como expresión. Después de todo, siempre puede codificar de alguna manera una máquina Turing que codifica un intérprete de un idioma con excepciones (por ejemplo, Java). Pero eso probablemente no sea lo que tiene en mente, por lo que debe imponer fuertes restricciones al concepto de "expresión" (por ejemplo, composición y / o abstracción completa).
Martin Berger

Respuestas:

11

En esta respuesta, tomaré "expresable" como "macroexpresable" en el sentido de Felleisen 1991, Sobre el poder expresivo de los lenguajes de programación . (Intuitivamente, una característica del lenguaje es macroexpresable si puede definirla como una transformación de fuente local, sin usar una transformación de programa completo).

Con esta definición, la respuesta es no : el control delimitado no es macroexpresable en el cálculo lambda + call / cc. Para expresar operadores de control delimitados usando call / cc. Para implementar los delimitadores de control (la parte de reinicio de shift / reset), necesita algún estado para simular las marcas de continuación, esencialmente para codificar una pila para simular las vidas dinámicas de las marcas de continuación.

Sin embargo, el control delimitado es un efecto universal, en el siguiente sentido. En su tesis doctoral , Andrzej Filinski demostró que cualquier efecto secundario expresable es codificable usando continuaciones delimitadas o call / cc y una sola celda de estado. Aproximadamente, un "efecto secundario expresable" es cualquier efecto cuyo tipo monádico se puede definir en términos de los tipos del lenguaje de programación.

Sorprendentemente, esta idea parece bastante interesante en la práctica. Durante la última década, Gordon Plotkin y John Power han defendido la idea de tomar una semántica algebraica de teorías de efectos : la idea es que especifique las operaciones de efectos secundarios que le interesan y las ecuaciones que espera que satisfagan, y luego genéricamente puedes obtener una semántica tomando la mónada libre sobre esta teoría.

Matija Pretnar y Andrej Bauer adoptaron este enfoque matemático, y luego lo implementaron en su lenguaje Eff para inventar una nueva construcción de lenguaje denominada "manejadores de efectos": puede escribir código que use un conjunto de características imperativas, y luego dar una semántica a las características imperativas escribiendo un conjunto de controladores que dicen cómo implementar cada operación efectiva.

Neel Krishnaswami
fuente
Pero si la definición es: "¿Puede implementar cualquier estructura de flujo de control usando Scheme y call / cc" (sin emulación), entonces la respuesta debe ser ? Mirando la discusión de LtU lambda-the-ultimate.org/node/966 parece que Oleg Kiselyouv implementó los cuatro operadores F en Scheme con call / cc: okmij.org/ftp/continuations/… - extracto "El código se basa on call / cc para capturar continuaciones no delimitadas, y utiliza una celda mutable global. Resulta que esto es suficiente para implementar [...] los otros operadores F ". ... "-F- a través de + F + F".
csl
Reconozco su uso de la "macro-expresibilidad" de Felleisen como marco para su respuesta, pero como puede ver, ya había cambiado mi pregunta para que significara específicamente "implementar [en el esquema] usando call / cc". Y aunque Oleg Kiselyov necesita introducir una celda global mutable para implementar los cuatro operadores F para continuaciones delimitadas, no creo que esto signifique una "reestructuración global importante del programa", prácticamente hablando, por supuesto.
csl
Voy a aceptar esta respuesta. También me gustaría señalar el texto en okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim que tiene punteros adicionales. También parece que se pueden usar continuaciones delimitadas de primera clase como shift / reset para implementar cualquier estructura de flujo de control. Desde el enlace: "Las continuaciones delimitadas de primera clase pueden expresar cualquier efecto computacional expresable, incluidas las excepciones y el estado mutable".
csl