Ceci est lié à Qu'est-ce que Call / CC? , mais je ne voulais pas Pour détourner cette question à mes propres fins, et certains de ses arguments comme l'analogie à SetJMP / Longjmp Evontez-moi. P>
Je pense avoir une idée suffisante sur la poursuite de la poursuite, j'y pense comme un instantané de la pile d'appels actuelle. Je ne veux pas aller dans la discussion pour laquelle cela pourrait être intéressant ou ce que vous pouvez faire avec les continuations. Ma question est plus spécifiquement, pourquoi dois-je fournir un argument de fonction à appeler / cc? Pourquoi n'appelle-t-il pas / cc vient de retourner la continuation actuelle, alors je pouvais faire tout ce que je veux avec elle (stockez-le, appelez-le, vous le nommez)? Dans un lien de cette autre question ( http: // communauté .schemewiki.org /? Call-with-courriel-continuation-for-c-programmeurs ), il parle "essentiellement, c'est juste un moyen propre pour obtenir la continuation avec vous et garder hors de la manière des sauts ultérieurs retour au point sauvé. ", mais je ne l'obtiens pas. Cela semble inutilement compliqué. P>
4 Réponses :
Ce serait moins polyvalent. Si vous voulez ce comportement, vous pouvez simplement faire:
(call/cc (lambda (x) x))
Merci d'avoir montré comment je pourrais dégrader à ce cas d'angle. Mais je voulais une explication, pas une solution.
Si vous utilisez une construction comme des émissions de Jay, vous pouvez saisir la suite, mais d'une certaine manière, la valeur qui est saisie est déjà gâtée car vous êtes déjà à l'intérieur de cette continuation. En revanche, Vous ne pouvez pas le faire avec l'opération que vous décrivez. Si vous essayez: p> alors vous obtenez une erreur concernant l'application de deux notes connexes supplémentaires: p> appel / cc code> peut être utilisé pour saisir la suite qui est toujours em> en attente de l'expression actuelle. Par exemple, l'une des utilisations les plus simples de la continuation consiste à mettre en place une sorte de
Abort code>:
9 code> comme procédure. Cela se produit car
abandon code> retourne au
let code> avec la nouvelle valeur de
9 code> - ce qui signifie que vous faites maintenant un deuxième tour de La même expression d'addition, sauf que maintenant
abandon code> est liée à
9 code> ... p>
appel / cc code> est em> un peu complexe en ce que cela prend une fonction - une construction conceptuellement plus facile à utiliser est
let / cc code> que vous pouvez trouver dans certaines implémentations telles que PLT Schéma. L'exemple ci-dessus devient
(let / cc Abort (+ 1 2 (Abort 9))) Code>. Li>
ol> p>
Donc, ce que vous dites en termes de ma question, est a) si la suite est immédiatement renvoyée, il est "gâté" parce que je suis à l'intérieur de la continuation. Mais je ne peux pas être dans une continuation à moins que je n'appelle ça. Si les continuations sont des valeurs de première classe, elles ne peuvent pas être gâtées en les transmettant, peuvent-ils ?! Ensuite, vous dites (b) Call / CC attraperait une continuation "en attente". Comment une valeur peut-elle être en attente? Vous dites également que la suite est «à l'extérieur» de l'expression actuelle. Je ne comprends pas vraiment ça. Combien la continuation capture-t-elle? Tout jusqu'à mais non inclure l'appel à appeler / cc ?!
Oui, vous êtes déjà à l'intérieur de la continuation. La chose à propos de la continuation est qu'elles représentent le calcul «futur» après l'expression de Call / CC actuel. Ainsi, après que vous ayez fini de (appeler / cc (Lambda (k) K)), vous passez immédiatement à la suite que Vous venez de capturer.
Remarque, BTW, que la vue de «une continuation représente la pile actuelle» est utile de la mettre en œuvre, mais de ne pas le comprendre. Une meilleure façon de le regarder si vous voulez comprendre qu'il est de le considérer comme le contexte. Par exemple, la suite qui devient liée à K dans (liste 1 2 (appel / cc (Lambda (k) k)) 3 4) est le contexte qui attend une réponse et procédera ensuite à évaluer 3 et 4, Ensuite, appliquez une liste sur les 5 valeurs. En d'autres termes, vous le considérez comme suit: (Liste 1 2 [...] 3 4). Cela peut être difficile à faire, car dans la plupart des cas, ce contexte est global. Voir ces références que j'ai signalées à.
Je suggère de commencer en vous demandant: Que signifie être une continuation de première classe?
La poursuite d'une expression est essentiellement constituée de deux pièces de données: première, la fermeture (c'est-à-dire l'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 des continuations de première classe, est donc celle qui comporte des structures de données qui encapsulent ces pièces et traite ces structures de données tout comme elles le feraient d'autres. P>
Call / CC est un moyen particulièrement élégant de réaliser Cette idée: la poursuite actuelle est emballée en tant que procédure qui encapsule ce qui est-à-faire - avec l'expression de l'expression comme quelle est la procédure lorsqu'elle est appliquée à l'expression; Pour représenter la suite de cette façon signifie simplement que la fermeture de cette procédure contient l'environnement sur le site, il a été invoqué. P>
Vous pouvez imaginer réaliser l'idée de continuations de première classe d'une autre manière. Ils ne seraient pas appelés / cc, et il est difficile pour moi d'imaginer comment une telle représentation pourrait être plus simple. P>
sur une note de séparation, envisagez la mise en œuvre de Let / CC que Eli mentionné, que je préfère Appeler BIND / CC: P>
(define-syntax bind/cc (syntax-rules () ((bind/cc var . body) (call/cc (lambda (var) . body)))))
Merci pour le poste, mais c'est encore une fois, trop loin de ma question à me laisser une réponse.
contre commun alors nesiquette Je réponds à ma propre question, mais plus comme éditeur que le fournisseur de la réponse. P>
Après un moment, j'ai commencé à une question similaire sur LTU . Après tout, ce sont les gars qui réfléchissent à la conception de la langue toute la journée, ne sont-ils pas, et l'un des réponses enfin frappé avec moi. Maintenant, les choses mentionnées ici, par ex. par Eli ou dans la question initiale, rendez-vous beaucoup plus de sens pour moi. Il s'agit de ce qui est inclus dans la continuation et où la suite appliquée s'installe. P>
Un de l'un des affiches chez LTU a écrit: P >
"Vous pouvez voir exactement comment Call / CC vous permet de" garder à l'écart ". Avec EM ou GET / CC, vous devez faire une sorte de test pour déterminer si vous avez un saut arrière ou juste la première appel. Fondamentalement, Call / CC conserve l'utilisation de la continuation de la continuation, alors qu'avec GET / CC ou EM, la suite contient son utilisation et (généralement), vous devez ajouter un test au début de la suite (c.-à-d. immédiatement après GET / CC / EM) pour séparer "Utilisation des pièces de continuation" à partir du "reste des pièces de continuation". " P> blockQuote>
qui l'a conduit à la maison pour moi. p>
Merci de toute façon! p>
Je pense que le prestataire de continuation EM (exclu du milieu) de Derek peut être mis en œuvre à l'aide de GET / CC. Si je trouve le temps, je vérifierai cela.
Regardant sur ce fil, il est parfaitement incertain pour moi ce que vous étiez après, et pourquoi vous avez trouvé le poste LTU illuminant. Peut-être que vous pourriez éditer cette question pour expliquer ces choses mieux?
Je pense que la question reflète toujours exactement le point que je me luttais avec, et c'était probablement le terme "test" de l'affiche de la LTU qui a frappé avec moi, car cela m'a fait penser aux conséquences de simplement retourner la continuation, lorsque vous invoquez ce. La citation de l'URL Schemewiki.org dans la question a essentiellement capturé tout cela, mais comme je l'ai dit, je ne l'ai pas eu. C'était juste dans mon visage, mais je n'ai pas "vu". La compréhension n'est pas liée de manière linéaire de l'information et, parfois, il a besoin d'une torsion.
Ok, je l'ai eu! Le point sur le chemin torsadé à la compréhension est juste, mais c'est un peu frustrant d'essayer de répondre à une question et de ne pas pouvoir comprendre pourquoi le questionneur l'a rejeté.