L'appel / cc de Scheme peut-il implémenter toutes les structures de flux de contrôle connues?


13

La page "Advanced Scheme: Some Naughty Bits" indique:

Les continuations sont une puissante structure de contrôle-flux à partir de laquelle presque toute autre structure de contrôle-flux [...] peut être dérivée.

Je pensais que Scheme call/cc, étant lié (*) à l'opérateur J de Peter Landin, pourrait être utilisé pour implémenter n'importe quelle structure de flux de contrôle connue?

Avec "structure de flux de contrôle", je pense spécifiquement à la description de Wikipédia , par exemple les exceptions, les coroutines, les fils verts, etc.

Plus précisément, existe-t-il des exemples de structures de flux de contrôle qui ne peuvent pas être implémentées à l'aide call/cc?

(*) Je n'ai pas pu déterrer de papier établissant qu'il call/ccest aussi puissant que l'opérateur J. Un article de Felleisen (que je n'ai pas lu et qui a certes du mal à le comprendre) étudie cela et semble conclure que même s'ils appartiennent à différentes classes de complexité, ils sont formellement équivalents.

(Notez également que j'ai mis à jour la question sur la base des commentaires ci-dessous)

Mise à jour

Sur la base de l'excellente réponse de @Neel ci-dessous, j'ai regardé des sites commentant des suites délimitées et non délimitées , et il semble en effet que call/cc, étant non délimité, ce n'est pas suffisant. Pendant ce temps, des suites délimitées de première classe (comme shift/reset) peuvent être utilisées, semble-t-il, pour exprimer toute structure de flux de contrôle.


5
Quelle est la définition officielle d'une "structure de flux de contrôle"?
Huck Bennett

4
Re: suites non délimitées. Avez-vous lu l'article référencé de Hayo Thielecke? L'affirmation actuelle est que les suites non limitées telles que prévues parcall/cc ne peuvent pas exprimer d'exceptions en l'absence d'État . (Comme le souligne Thielecke, des exceptions peuvent être implémentées en passant autour de deux continuations, une pour le programme et l'autre pour le gestionnaire d'exceptions, mais cela nécessite plus que juste call/cc.)
rici

@Rici: Je n'ai survolé que les premières pages. (La lecture des articles me prend beaucoup de temps). Merci pour le commentaire!
csl

@HuckBennett Je n'ai pas de définition formelle, mais de manière informelle, je veux dire ce qu'elle décrit à fr.wikipedia.org/wiki/Control_flow - en particulier, je veux dire que vous pouvez utiliser des continuations pour exprimer, et plus important encore, pour implémenter, des coroutines, les fils verts, les exceptions, les instructions d'échappement, l' ambopérateur-, etc.
csl

2
@csl En plus de préciser ce que signifie "structure de flux de contrôle", vous devez également être plus clair sur ce que signifie "exprimer" quelque chose. C'est un problème difficile, et la réponse à votre question dépend fortement de ce que vous comptez comme expression. Après tout, vous pouvez toujours coder d'une manière ou d'une autre une machine Turing qui code un interprète d'une langue avec des exceptions (par exemple Java). Mais ce n'est probablement pas ce que vous avez en tête, vous devez donc imposer de fortes contraintes au concept d '"expression" (par exemple la compositionnalité et / ou l'abstraction complète).
Martin Berger

Réponses:


11

Dans cette réponse, je considérerai "expressible" comme "macro-expressible" au sens de Felleisen 1991, On The Expressive Power of Programming Languages . (Intuitivement, une fonction de langage est macro-exprimable si vous pouvez la définir comme une transformation source locale, sans utiliser une transformation de programme entier.)

Avec cette définition, la réponse est non : le contrôle délimité n'est pas macro-expressible dans le lambda-calcul + appel / cc. Pour exprimer des opérateurs de contrôle délimités à l'aide de call / cc. Afin d'implémenter les délimiteurs de contrôle (la partie réinitialisation de shift / reset), vous avez besoin d'un état pour simuler les marques de continuation, essentiellement pour coder une pile pour simuler les durées de vie dynamiques des marques de continuation.

Cependant, le contrôle délimité est un effet universel, dans le sens suivant. Dans sa thèse de doctorat , Andrzej Filinski a montré que tout effet secondaire exprimable est codable en utilisant soit des continuations délimitées, soit un appel / cc et une seule cellule d'état. En gros, un "effet secondaire exprimable" est tout effet dont le type monadique peut être défini en termes de types de langage de programmation.

Étonnamment, cette idée semble assez intéressante dans la pratique. Au cours de la dernière décennie, Gordon Plotkin et John Power ont défendu l'idée de prendre une sémantique algébrique des théories des effets : l'idée est que vous spécifiez les opérations d'effets secondaires qui vous intéressent et les équations que vous attendez qu'elles satisfassent, puis vous pouvez génériquement obtenir une sémantique en prenant la monade libre sur cette théorie.

Matija Pretnar et Andrej Bauer ont adopté cette approche mathématique, puis l'ont implémentée dans leur langage Eff pour inventer une nouvelle construction de langage appelée "gestionnaires d'effets": vous pouvez écrire du code qui utilise un ensemble de fonctionnalités impératives, puis donner aux fonctionnalités impératives une sémantique en écrivant un ensemble de gestionnaires qui expliquent comment implémenter chaque opération efficace.


Mais si la définition est: "Pouvez-vous implémenter n'importe quelle structure de flux de contrôle en utilisant Scheme et appeler / cc" (sans émulation), alors la réponse doit être oui ? En regardant la discussion LtU lambda-the-ultimate.org/node/966, il semble qu'Oleg Kiselyouv a implémenté les quatre opérateurs F dans Scheme avec call / cc: okmij.org/ftp/continuations/… - extrait "Le code repose on call / cc pour capturer des continuations indéfinies, et utilise une cellule globale mutable. Il s'avère que ceci est suffisant pour implémenter [...] les autres opérateurs F ". ... "-F- à + F + F".
csl

Je reconnais que vous utilisez la "macro-expressibilité" de Felleisen comme cadre pour votre réponse, mais comme vous pouvez le voir, j'avais déjà changé ma question pour signifier spécifiquement "implémenter [dans le schéma] en utilisant call / cc". Et bien qu'Oleg Kiselyov doive introduire une cellule globale mutable pour implémenter les quatre opérateurs F pour des continuations délimitées, je ne pense pas que cela équivaut à une "restructuration globale majeure du programme" --- pratiquement parlant, bien sûr.
csl

Je vais accepter cette réponse. Je voudrais également pointer le texte sur okmij.org/ftp/continuations/undelimited.html#delim-vs-undelim qui contient des pointeurs supplémentaires. Il semble également que des continuations délimitées de première classe comme shift / reset puissent être utilisées pour implémenter n'importe quelle structure de flux de contrôle. À partir du lien: "Les suites délimitées de première classe peuvent exprimer tout effet de calcul exprimable, y compris les exceptions et l'état mutable."
csl
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.