Как запустить захваченные текущие продолжения в Racket

Я изучаю call/cc в Racket вдоль линий бумаги Продолжение на примере: исключения, поиск с перемещением во времени, генераторы, потоки и сопрограммы 1.

В документе упоминается, что наиболее выгодный API получен из call/cc путем предоставления процедуры lambda (cc) (cc cc). Я понимаю, что этот конкретный вызов call/cc возвращает основной программе текущий объект первого класса продолжения.

В следующем примере статья называет все это (right-now).

Что я вижу, так это то, что внутри того же примера объект cc, возвращаемый вышеупомянутым вызовом call/cc, всегда запускается впоследствии, применяя его к себе. Вот чего я не понимаю.

Я не вижу, что такого особенного в cc как значение, поэтому я попытался запустить его как функцию с (cc ()), или (cc (lambda () ())), или даже (cc "whatever") и (cc). Никакой радости: видимо, продолжение хочет только это приложение, чтобы начать работать.

Почему это? Какой пример ясно иллюстрирует уникальность запуска cc путем выполнения (cc cc) ?


person Marco Faustinelli    schedule 26.10.2015    source источник
comment
Кстати, обратите внимание, что пустое приложение () является ошибкой в ​​Racket. Попробуйте что-нибудь вроде (cc 42).   -  person soegaard    schedule 27.10.2015
comment
Я тоже так пробовал :-( Текст изменен :-)   -  person Marco Faustinelli    schedule 27.10.2015


Ответы (1)


In

(let ((cc (current-continuation)))
  ...)

Продолжение (current-continuation) это

(lambda (_)
  (let ((cc _))
    ...)

Назовите это продолжение c0.

Определение current-continuation:

(define (current-continuation)
  (call/cc (lambda (cc) (cc cc))))

Итак, call/cc вызывает (lambda (cc) (cc cc)) с c0 в качестве аргумента:

  ((lambda (cc) (cc cc)) c0)
= (c0 c0)

Вставка значения c0:

((lambda (_)
   (let ((cc _))
     ...)
 c0)

который становится:

   (let ((cc c0))
     ...)

Это означает, что внутри ... идентификатор cc теперь привязан к значению c0.

Если (c0 42) встречается в ...

Мы получаем:

   (c0 42)
= ((lamdba (_)
     (let ((cc _))
      ...)
   42)
= (let ((cc 42))
     ...)

И теперь cc привязано к значению 42.

В примере используются (procedure? cc) и (future-value? cc) для проверки того, связано ли cc с продолжением (если (procedure? cc) верно) и/или другим значением (будущее значение здесь 42).

So in:

(define (current-continuation)
  (call/cc (lambda (cc) (cc cc))))

значение, переданное в (lambda (cc) (cc cc))), является продолжением. Если мы хотим получить его в свои руки, нам нужно вернуть его, и мы делаем это, передавая его в продолжение. т.е. (cc something) что-то вернет, а так как мы хотим получить само продолжение, то используем (cc cc).

person soegaard    schedule 26.10.2015
comment
Это подсказка! (current-continuation) = (call/cc). Я проглядел первую пару скобок. Спасибо! - person Marco Faustinelli; 27.10.2015