2010-06-13 5 views
4

J'ai du mal à comprendre le comportement du programme du schéma suivant:Aide-dynamique du vent et appel/cc

(define c 
    (dynamic-wind 
    (lambda() (display 'IN)(newline)) 
    (lambda() (call/cc (lambda (k) 
        (display 'X)(newline) 
        k))) 
    (lambda() (display 'OUT)(newline)))) 

Si je comprends bien, c sera lié au continution créé juste avant « (affiche 'X) ".

Mais utiliser c semble se modifier! La définition des impressions ci-dessus (comme je m'y attendais) IN, X et OUT:

IN 
X 
OUT 

Et il est une procédure:

#;2> c 
#<procedure (a9869 . results1678)> 

Maintenant, je pense que quand il est appelé à nouveau, X serait imprimé, et ce n'est pas!

#;3> (c) 
IN 
OUT 

Et maintenant c n'est plus une procédure, et une deuxième invocation de c ne fonctionnera pas!

#;4> c ;; the REPL doesn't answer this, so there are no values returned 
#;5> (c) 

Error: call of non-procedure: #<unspecified> 

     Call history: 

     <syntax>   (c) 
     <eval>    (c) <-- 

Je me attendais à ce que chaque invokation à (c) ferait la même chose - imprimer IN, X et OUT. Qu'est-ce que je rate?

Répondre

8

L'exécution de cette Racket est un peu plus utile:

-> (define c 
    (dynamic-wind 
     (lambda() (display 'IN)(newline)) 
     (lambda() (call/cc (lambda (k) 
          (display 'X)(newline) 
          k))) 
     (lambda() (display 'OUT)(newline)))) 
IN 
X 
OUT 
-> c 
#<continuation> 
-> (c) 
IN 
OUT 
define-values: context (defining "c") expected 1 value, received 0 values 
-> (c 99) 
IN 
OUT 
-> c 
99 

Notez que spécifiquement c lié à une obtient la valeur de continuation - parce que votre expression retourne k comme valeur. Et k lui-même est la continuation de l'expression de valeur, ce qui signifie que cette continuation est celle qui attend d'obtenir une valeur à être liée à c. Donc, l'invoquer nécessite une seule valeur, comme le requiert Racket, ce qui permet de clarifier ce qui se passe ici (le MIT Scheme semble le traiter silencieusement comme non spécifié). Quoi qu'il en soit, l'application de cette continuation sur 99 signifie que la valeur de retour de cette expression est 99 - vous revenez dans le contexte (impression IN) et renvoyez 99 pour être lié à c, et d'imprimer OUT pour sortir. Vous avez maintenant modifié c pour avoir cette 99 à la place, donc vous ne pouvez pas l'appeler une troisième fois.

+0

Oh, je vois! Maintenant, j'ai l'impression que c'était une question vraiment idiote après tout. Merci beaucoup! – josh

+1

@Eli: "vous ne pouvez donc pas l'appeler une troisième fois" - sauf si vous appelez toujours (cc), qui lie c à la suite d'une procédure définissant c ... :-) – Jay

+1

@Jay: vous a raison, bien sûr. Je me concentrais sur la configuration de josh, sauf que Racket nécessite une certaine valeur à envoyer - donc l'utilisation de 'c' l'aurait rendu plus confus. –

Questions connexes