Following are two case which have different behaviors regarding the value of i across calls to stored continuations. How can the difference be explained?
Case A
>(define cc #f)
>(define (x)
(let ((i 0))
(set! i (+ i 100))
(+ i (+ i (call/cc (lambda (k) (set! cc k) 1)))) ; call/cc is not included by set!
(set! i (+ i 10))
i))
> (x)
110
> (cc 50) ; the context variable i changes as cc calling
120
> (cc 50)
130
Case B
> (define cc #f)
> (define (x)
(let ((i 0))
(set! i (+ i 100))
(set! i (+ i (call/cc (lambda (k) (set! cc k) 1)))) ; call/cc is included by set!
(set! i (+ i 10))
i))
> (x)
111
> (cc 50) ; the context variable i always be 0, not changing as cc calling
160
> (cc 50)
160
I'm making assumptions here, so forgive me if I'm wrong :)
I was able to reproduce this in Racket and in my pet Scheme implementation. The problem may hide in the way the continuations are implemented in the specific Scheme implementation. So here are my assumptions:
call/ccand the copy contains the evaluated procedure arguments.This means that in
iin the+application is evaluated beforecall/ccand its value100is stored in the stack. Whenccis called it does not reevaluateiand instead uses the value100, evaluated before. So when calling(cc 50)you getIf you switch the places of
call/ccandi, theniwill be reevaluated and thus you get correct results.