Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Help with dynamic-wind and call/cc

I am having some trouble understanding the behavior of the following Scheme program:

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

As I understand, c will be bound to the continution created right before "(display 'X)".

But using c seems to modify itself! The define above prints (as I expected) IN, X and OUT:

IN
X
OUT

And it is a procedure:

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

Now, I would expect that when it is called again, X would be printed, and it is not!

#;3> (c)
IN
OUT

And now c is not a procedure anymore, and a second invokation of c won't work!

#;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)    <--

I was expecting that each invokation to (c) would do the same thing -- print IN, X, and OUT. What am I missing?

like image 875
josh Avatar asked Jun 13 '10 11:06

josh


1 Answers

Running this in Racket is a little more helpful:

-> (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

Note specifically that c gets bound to a continuation value -- because your expression returns k as the value. And k itself is the continuation of the value expression, which means that this continuation is the one waiting to get a value to be bound to c. So invoking it requires a single value, as Racket requires, which helps clarifying what happens here (MIT Scheme seems to silently treat it as unspecified). Anyway, applying this continuation on 99 means that the return value from that expression is 99 -- so you jump back into the context (printing IN) and return 99 to be bound to c, and print OUT on your way out. You've now modified c to have that 99 instead, so you can't call it a third time.

like image 105
Eli Barzilay Avatar answered Sep 28 '22 09:09

Eli Barzilay