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/cc
and the copy contains the evaluated procedure arguments.This means that in
i
in the+
application is evaluated beforecall/cc
and its value100
is stored in the stack. Whencc
is called it does not reevaluatei
and instead uses the value100
, evaluated before. So when calling(cc 50)
you getIf you switch the places of
call/cc
andi
, theni
will be reevaluated and thus you get correct results.