Использование call/cc для создания цикла. давай начнем

Оба следующих блока кода должны (на мой взгляд) быть бесконечными циклами

Это работает

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

(define l 0)
(define i 0)

((lambda ()
   (call/cc
    (lambda (k)
      (set! l k)))
   (write i)
   (newline)
   (set! i (+ i 1))
   (l "ignore")))

Это не работает:

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

(define l 0)
(define i 0)

(begin
   (call/cc
    (lambda (k)
      (set! l k)))
   (write i)
   (newline)
   (set! i (+ i 1))
   (l "ignore"))

Единственная разница в том, что в одном используется лямбда, а в другом — начальный блок. Почему второй блок кода не работает?

Спасибо


person timkomip    schedule 16.04.2013    source источник


Ответы (1)


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

Продолжение объединенного выражения call/cc на самом деле является пустым продолжением, поскольку каждое выражение верхнего уровня оценивается отдельно (т. е. в пустом продолжении). Вы можете проверить это, поставив let вокруг begin, что заставит его находиться в позиции выражения. Тогда это будет бесконечный цикл, как вы ожидаете.

person Asumu Takikawa    schedule 16.04.2013
comment
Спасибо! Кроме того, что подразумевается под объединением всех своих аргументов с окружающим контекстом? - person timkomip; 17.04.2013
comment
(начало (начало 1) (начало 2 3) (начало 4)) расширится до (начало 1 2 3 4). Содержимое внутреннего начала встраивается в контекст внешнего начала. - person soegaard; 17.04.2013