Суть call-with-concurrent-continuation
, или сокращенно call/cc
, заключается в возможности захвата контрольных точек или продолжений во время выполнения программы. Затем вы можете вернуться к этим контрольным точкам, применив их как функции.
Вот простой пример, где продолжение не используется:
> (call/cc (lambda (k) (+ 2 3)))
5
Если вы не используете продолжение, трудно заметить разницу. Вот некоторые из них, где мы на самом деле используем это:
> (call/cc (lambda (k) (+ 2 (k 3))))
3
> (+ 4 (call/cc (lambda (k) (+ 2 3))))
9
> (+ 4 (call/cc (lambda (k) (+ 2 (k 3)))))
7
Когда вызывается продолжение, поток управления возвращается туда, где продолжение было захвачено call/cc
. Думайте о выражении call/cc
как о дыре, которая заполняется тем, что передается k
.
list-iter
- значительно более сложное использование call/cc
, и его может быть трудно начать использовать. Во-первых, вот пример использования:
> (define i (list-iter '(a b c)))
> (i)
a
> (i)
b
> (i)
c
> (i)
list-ended
> (i)
list-ended
Вот эскиз того, что происходит:
list-iter
возвращает процедуру без аргументов i
.
- Когда вызывается
i
, мы немедленно получаем продолжение и передаем его control-state
. Когда это продолжение, связанное с return
, будет вызвано, мы немедленно вернемся к тому, кто вызвал i
.
- Для каждого элемента в списке мы берем новое продолжение и переписываем определение
control-state
этим новым продолжением, что означает, что мы возобновим оттуда в следующий раз, когда появится шаг 2.
- После установки
control-state
в следующий раз мы передаем текущий элемент списка обратно в продолжение return
, получая элемент списка.
- Когда
i
вызывается снова, повторяйте с шага 2, пока for-each
не выполнит свою работу для всего списка.
- Вызвать продолжение
return
с помощью 'list-ended
. Поскольку control-state
не обновляется, он будет возвращать 'list-ended
каждый раз, когда вызывается i
.
Как я уже сказал, это довольно сложное использование call/cc
, но я надеюсь, что этого достаточно, чтобы пройти через этот пример. Для более мягкого введения в продолжения, я бы порекомендовал подобрать Закаленный мошенник .