Reputation: 61
In the book Lisp in Small Pieces, there is the following example code, which is intended to demo that call/cc
could simulate goto.
(define (fact n)
(let ((r 1) (k 'void))
(call/cc (lambda (c) (set! k c) 'void))
(set! r (* r n))
(set! n (- n 1))
(if (= n 1) r (k 'recurse))))
However, I'm not sure if I'm misunderstanding something, but I cannot see that this is the way call/cc
would simulate goto. When k
is applied in the last line, the restored continuation has the r
and n
of the original continuation, whose values are not changed by the two set!
applications. So the entire loop will never terminate.
Is the book wrong in this example? Or did I miss anything?
Upvotes: 3
Views: 688
Reputation: 85883
the restored continuation has the r and n of the original continuation, whose values are not changed by the two set! applications.
Nope; that's the important part; the changes to the values are visible. They're not reset. I'm not sure whether the question should be considered a duplicate or not, but this came up in call-with-current-continuation - state saving concept as well, where the asker noted that (look at the question for the whole context):
Calling next 3 times produces 0, 1 and 'done. That means when state used the function k given by generator it didn't restore the state of the program.
You could test this very simply by printing the values of r and n after saving the continuation. You'll see that the updated values are there. For instance:
(define (fact n)
(let ((r 1) (k 'void))
(call-with-current-continuation (lambda (c) (set! k c) 'void))
(display "r: ") (display r) (newline)
(display "n: ") (display n) (newline)
(set! r (* r n))
(set! n (- n 1))
(if (= n 1) r (k 'recurse))))
> (fact 6)
r: 1
n: 6
r: 6
n: 5
r: 30
n: 4
r: 120
n: 3
r: 360
n: 2
720
Also see:
Upvotes: 1