Continuation
Source: Wikipédia sous licence CC-BY-SA 3.0.
La liste des auteurs de cet article est disponible ici.

Introduction

Wiktprintable without text.svg

Voir « continuation » sur le Wiktionnaire.

En informatique, la continuation d'un système désigne son futur, c'est-à-dire la suite des instructions qu'il lui reste à exécuter à un moment précis. C'est un point (Graphie) de vue (La vue est le sens qui permet d'observer et d'analyser l'environnement par la réception et l'interprétation des rayonnements lumineux.) pour décrire l'état de la machine.

Dans les langages de programmation

Utilisation explicite

Dans certains langages de programmation, les continuations peuvent être manipulées explicitement en tant qu'objets du langage à part entière : on peut stocker la continuation (En informatique, la continuation d'un système désigne son futur, c'est-à-dire la suite des instructions qu'il lui reste à exécuter à un moment précis. C'est un point de vue pour décrire...) courante dans une variable (En mathématiques et en logique, une variable est représentée par un symbole. Elle est utilisée pour marquer un rôle dans une formule, un prédicat ou un algorithme. En...) que l'on peut donc manipuler en tant que telle ; puis plus loin, on peut restaurer la continuation, ce qui a pour effet de dérouter l'exécution du programme actuel vers le futur que l'on avait enregistré.

En C, l'instruction (Une instruction est une forme d'information communiquée qui est à la fois une commande et une explication pour décrire l'action, le comportement, la méthode ou la tâche qui devra commencer, se terminer, être conduit, ou exécuté.) setjmp permet de capturer une continuation (en fait, stocker la valeur du compteur ordinal dans une variable), et l'instruction longjmp permet de dérouter le programme vers une continuation enregistrée.

En programmation fonctionnelle (Un langage fonctionnel est un langage de programmation dont la syntaxe et les caractéristiques encouragent la programmation fonctionnelle. Le langage fonctionnel le plus ancien est le Lisp, créé en 1958 par...), une continuation prend la forme d'une fonction qui peut prendre divers arguments (qui influent sur la valeur de retour de l'instruction qui avait "saisi" la continuation courante) et qui n'a pas de valeur de retour (en fait ne finit pas du point de vue de l'appelant, car le programme est dérouté).

Exemple en Scheme :

       (define fonction1         (lambda (k)            (begin (display "Toto")                  (k "Titi")                  (display "Tata")       )))       (display (call-with-current-continuation fonction1))      

a pour sortie à l'écran :

      Toto      Titi      

L'instruction « (display "Tata") » a été ignorée.

Explication :

  • nous commençons par définir une fonction «fonction1», puis nous demandons d'afficher le résultat («display») de «(call-with-current-continuation fonction1)».
  • l'instruction «call-with-current-continuation» a pour effet de capturer la continuation courante (qui est d'afficher la valeur de retour grâce à la commande (Commande : terme utilisé dans de nombreux domaines, généralement il désigne un ordre ou un souhait impératif.) «display», puis de terminer le programme) et de l'envoyer en argument à la fonction «fonction1»
  • or cette fonction est une séquence de trois instructions, dont la deuxième est d'appeler la continuation «k» passée en argument, donc de sortir de la fonction puisque la continuation aura été capturée à l'extérieur.
  • après cela, la continuation s'exécute normalement : «display» s'exécute avec la valeur de retour de «(call-with-current-continuation fonction1)», qui avait été fournie en argument de «k», c'est-à-dire "Titi"; puis le programme termine.

Utilisation implicite : les exceptions

Cependant l'utilisation la plus courante de la notion de continuation se fait de manière implicite, lorsque l'on manipule les exceptions.

En effet, le bloc d'exception n'est qu'une structure syntaxique pour dire qu'avant d'exécuter, on a enregistré la continuation courante (sans le bloc) précédée de l'exécution de la routine de traitement d'exception, et que lorsque une exception sera rencontrée pendant exécution du bloc, alors on appellera la continuation correspondante.

Exemple en OCaml :

       try          50 / 0        with          Division_by_zero -> 42 ;;      

retourne

      -: int = 42      

Explication : avant d'exécuter la division (La division est une loi de composition qui à deux nombres associe le produit du premier par l'inverse du second. Si un nombre est non nul, la fonction "division par ce nombre"...), OCaml enregistre la continuation consistant à retourner 42 puis à finir l'exécution dans l'exception «Division_by_zero». Puis OCaml essaye de lancer la division qui résulte en l'appel de cette exception, à laquelle justement on venait d'associer une continuation.

Programmation par continuation

En programmation fonctionnelle (En mathématiques, le terme fonctionnelle se réfère à certaines fonctions. Initialement, le terme désignait les fonctions qui en prennent d'autres en...), la programmation par continuation désigne une technique de programmation consistant à n'utiliser que de simples appels de fonction qui prennent pour argument leur propre continuation, au lieu d'appeler séquentiellement des fonctions, ou d'exécuter une fonction sur le résultat de la précédente. Ces fonctions se retrouvent en quelque sorte maîtresses de leur destin, et ne se contentent plus de subir le contexte (Le contexte d'un évènement inclut les circonstances et conditions qui l'entourent; le contexte d'un mot, d'une phrase ou d'un texte inclut les mots qui...).

Un des enjeux de la programmation par continuation est d'obtenir un programme récursif terminal, qui après compilation et optimisation ne requiert plus d'empiler les appels successifs imbriqués. Ceci se traduit par une moindre consommation de mémoire (D'une manière générale, la mémoire est le stockage de l'information. C'est aussi le souvenir d'une information.).

Exemple : calcul de la factorielle, en OCaml

Version «classique» :

       let rec fact = function           | 0 -> 1          | n -> n*(fact (n - 1));;      

Version par continuation (qui est stricto sensu récursive terminale, mais pourrait être bien simplifiée pour consommer moins de mémoire, en stockant l'accumulation du résultat plutôt qu'une continuation, qui elle est de plus en plus grosse, ce qui fait qu'on n'a rien gagné sur le plan pratique) :

       let rec fact k = function         | 0 -> (k 1)         | n -> fact (fun x -> k (n * x)) (n - 1);;      

(Si on veut juste calculer la factorielle de 5 et l'afficher, la syntaxe d'appel serait alors :)

       print_int (fact 5);;      

dans le premier cas et

      fact print_int 5      

dans le second.

Page générée en 0.183 seconde(s) - site hébergé chez Amen
Ce site fait l'objet d'une déclaration à la CNIL sous le numéro de dossier 1037632
Ce site est édité par Techno-Science.net - A propos - Informations légales
Partenaire: HD-Numérique