Dong Feng
Dong Feng

Reputation: 61

Does call/cc simulate goto this way?

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

Answers (1)

Joshua Taylor
Joshua Taylor

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

Related Questions:

Also see:

Upvotes: 1

Related Questions