Question

Ceci est lié à Qu'est-ce que l'appel / cc , mais je ne voulais pas de détourner cette question à mes propres fins, et certains de ses arguments comme l'analogie avec setjmp / longjmp me échapper.

Je crois avoir une idée suffisante de ce que la poursuite est, je pense comme un instantané de la pile d'appel en cours. Je ne veux pas entrer dans la discussion pourquoi cela pourrait être intéressant ou ce que vous pouvez faire avec continuations. Ma question est plus précisément, pourquoi dois-je fournir un argument de fonction à appeler / cc? Pourquoi ne pas simplement appeler / cc retour la poursuite en cours, pour que je puisse faire ce qui me plaît avec elle (la stocker, l'appeler, vous le nom)? Dans un lien de cette autre question ( http: // communauté .schemewiki.org /? appelez-avec-courant de continuation pour-C-programmeurs ), il parle de « Essentiellement, il est juste un moyen propre pour obtenir la continuation à vous et garder hors de la voie de sauts suivants retour au point sauvé. ", mais je ne suis pas l'obtenir. Il semble inutilement compliqué.

Était-ce utile?

La solution 4

Contre commune SO nétiquette Je réponds à ma propre question, mais plus que l'éditeur que le fournisseur de la réponse.

Après un certain temps j'ai commencé une question similaire sur LTU . Après tout, ce sont les gars qui méditent la conception du langage toute la journée, ils ne sont pas, et l'un des réponses a finalement botté avec moi. Maintenant, les choses mentionnées ici, par exemple par Eli ou dans la question initiale, me faire beaucoup plus de sens. Il est tout au sujet de ce qui sera inclus dans la suite, et où la poursuite appliquée installe.

L'une des affiches à LTU écrit:

  

"Vous pouvez voir exactement comment appeler / cc vous permet de « garder hors du chemin. » Avec em ou obtenir / cc que vous devez faire une sorte de test pour déterminer si vous avez un arrière-saut ou l'initiale appel. en fait, appel / cc maintient l'utilisation de la poursuite de la poursuite, alors qu'avec get / cc ou em, la suite contient son utilisation et donc (en général) vous devez ajouter un test au début de la poursuite (c.-à- immédiatement après get / cc / em) pour séparer les « en utilisant les pièces de continuation » du « reste de la suite » parties ".

Qu'il conduit à la maison pour moi.

Merci les gars quand même!

Autres conseils

Si vous utilisez une construction comme Jay montre, vous pouvez alors saisir la poursuite, mais d'une manière, la valeur qui est saisi est déjà gâté parce que vous êtes déjà à l'intérieur que la poursuite. En revanche, call/cc peut être utilisé pour saisir la poursuite qui est toujours en attente en dehors de l'expression actuelle. Par exemple, l'un des plus simples utilisations de continuations est de mettre en œuvre une sorte d'un abort:

(call/cc (lambda (abort)
           (+ 1 2 (abort 9))))

Vous ne pouvez pas le faire avec l'opération que vous décrivez. Si vous essayez:

(define (get-cc) (call/cc values))
(let ([abort (get-cc)]) (+ 1 2 (abort 9)))

vous obtenez une erreur sur l'application 9 comme une procédure. Cela se produit parce que abort revient au let avec la nouvelle valeur de 9 - ce qui signifie que vous faites maintenant un deuxième tour de la même expression d'addition, sauf que maintenant abort est lié à 9 ...

Deux notes connexes supplémentaires:

  1. Pour une belle introduction pratique à continuations, voir PLAI .
  2. call/cc un peu complexe en ce sens qu'il prend dans une fonction - un plan conceptuel plus facile à utiliser construction est let/cc que vous pouvez trouver dans certaines implémentations comme PLT Scheme. L'exemple ci-dessus devient (let/cc abort (+ 1 2 (abort 9))).

Ce serait moins polyvalent. Si vous voulez que le comportement, vous pouvez simplement faire:

(call/cc (lambda (x) x))

Vous pouvez jeter un oeil sur les usages par exemple des continuations dans « Ferguson Darrell et Dwight Deugo. « Appel avec des modèles de continuation en cours ». 8e Conférence sur les langues des programmes Patron. Septembre 2001. » ( http://library.readscheme.org/page6.html ) et essayer de les réécrire au moyen d'un appel / cc-retour, définis comme ci-dessus.

Je suggère de commencer par vous demander: qu'est-ce que cela signifie d'être une continuation de première classe

?

La poursuite de l'expression est essentiellement constitué de deux éléments de données: d'une part, la fermeture (à savoir, environnement) de cette expression; et deuxièmement, une représentation de ce qui devrait être fait avec le résultat de l'expression. Une langue avec continuations de première classe, alors, est celui qui a des structures de données encapsulant ces parties, et qui traite ces structures de données comme il le ferait tout autre.

appel / cc est une manière particulièrement élégante pour réaliser cette idée: la poursuite actuelle est conditionnée comme une procédure qui encapsule ce que-être à est-fait-avec-la-expression ce que la procédure ne lorsqu'elle est appliquée à l'expression; pour représenter la poursuite de cette manière signifie simplement que la fermeture de cette procédure contient l'environnement sur le site, il a été invoqué.

Vous pouvez imaginer la réalisation de l'idée de continuations de première classe d'une autre manière. Ils ne seraient pas appeler / cc, et il est difficile pour moi d'imaginer comment une telle représentation pourrait être plus simple.

Sur une note d'adieu, envisager la mise en œuvre de let / cc que Eli mentionné, que je préfère appeler bind / cc:

(define-syntax bind/cc
    (syntax-rules ()
        ((bind/cc var . body)
             (call/cc (lambda (var) . body)))))

Et comme un exercice, comment voulez-vous mettre en œuvre appel / cc basé sur bind / cc?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top