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
Смежные вопросы:
Также см:
- Объяснять различное поведение переменных, на которые ссылаются в продолжениях? (не очень полезно объяснять поведение, но это связано)