Call/cc симулирует goto таким образом?

В книге Lisp in Small Pieces приведен следующий пример кода, который предназначен для демонстрации того, что call/cc мог симулировать 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))))

Тем не менее, я не уверен, что я что-то неправильно понимаю, но я не вижу, что это путь call/cc будет имитировать goto. когда k применяется в последней строке, восстановленное продолжение имеет r а также n оригинального продолжения, значения которого не изменены двумя set! Приложения. Таким образом, весь цикл никогда не закончится.

Книга не так в этом примере? Или я что-то пропустил?

1 ответ

восстановленное продолжение имеет r и n исходного продолжения, значения которого не изменяются двумя наборами! Приложения.

Нету; это важная часть; изменения значений видны. Они не сбрасываются. Я не уверен, должен ли вопрос рассматриваться как дубликат или нет, но это возникло в вызове с текущим продолжением - также и в концепции сохранения состояния, где спрашивающий заметил это (посмотрите на вопрос для всего контекста):

Вызов следующий 3 раза производит 0, 1 и 'готово. Это означает, что когда состояние использовало функцию k, заданную генератором, оно не восстанавливало состояние программы.

Вы можете проверить это очень просто, напечатав значения r и n после сохранения продолжения. Вы увидите, что обновленные значения есть. Например:

(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

Смежные вопросы:

Также см:

Другие вопросы по тегам