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?
Running this in Racket is a little more helpful:
Note specifically that
cgets bound to a continuation value — because your expression returnskas the value. Andkitself is the continuation of the value expression, which means that this continuation is the one waiting to get a value to be bound toc. 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 (printingIN) and return 99 to be bound toc, and printOUTon your way out. You’ve now modifiedcto have that 99 instead, so you can’t call it a third time.