Бесконечный цикл при использовании call-with-current-continue в схеме

Я читал о call-with-current-continuation, особенно в Scheme, и читал различные статьи на многих веб-сайтах. Однако я до сих пор не понимаю, как работает поток управления при использовании call-with-current-continuation.

Например, учитывая приложенный ниже код, как вызывается продолжение и всякий раз, когда оно вызывается, как управление проходит через тело этой процедуры?

 (define call/cc call-with-current-continuation)
 (define showit (lambda (a b) 
                  (begin (display a) (display b) (display " "))))

 (define f
  (lambda (n)
     (let ((p (call/cc (lambda (k) k))))
         (begin
           (showit ’f= n)
          p))))

Кроме того, когда эта процедура запускается с использованием ((f 2) (f 4)), это приводит к бесконечному циклу с таким шаблоном:

введите здесь описание изображения

Может ли кто-нибудь объяснить причину бесконечного цикла? Примечание: использование Drracket с R5RS


person New User    schedule 14.10.2018    source источник


Ответы (1)


Call / cc возвращает функцию, которая продолжает окружающие вычисления. При его вызове управление возвращается в то место, откуда была взята функция, со значением, присвоенным функции.

В этом примере (let ((p (call/cc (lambda (k) k)))) ...), p задана функция продолжения. Если бы p затем был вызван (p 3), элемент управления вернулся бы к let-форме, как это было (let ((p 3)) ...).

((f 2) (f 4)) жонглирует продолжениями из (f 2) и (f 4), что приводит к бесконечному циклу. Я попытался объяснить последовательность действий ниже:

=> ((f 2) (f 4))
  => (f 2) ;; first (f 2)
       call/cc returns the current continuation (lets say "cc1") into p
       display f=2
       return cc1
=> (cc1 (f 4))
  => (f 4) ;; first (f 4)
       call/cc returns the current continuation cc2 into p
       display f=4
       return cc2
=> (cc1 cc2)
     cc1 goes back to the first (f 2), but call/cc returns now cc2 into p
     display f=2
     returns cc2 from the first (f 2)
=> (cc2 (f 4))
  => (f 4) ;; second (f 4)
       call/cc returns cc3 into p
       display f=4
       return cc3
=> (cc2 cc3)
     cc2 goes back to the first (f 4), but p gets cc3
     display f=4
     returns cc3 from the first (f 4)
=> (cc1 cc3)
     cc1 goes back to the first (f 2), but p gets cc3
     display f=2
     returns cc3 from the first (f 2)
=> (cc3 (f 4))
  => (f 4) ;; third (f 4)
       display f=4
  <= cc4
=> (cc3 cc4)
  => (f 4) ;; second again
       display f=4
  <= cc4
=> (cc2 cc4)
  => (f 4) ;; first again
       display f=4
  <= cc4
=> (cc1 cc4)
  => (f 2) ;; first again
       display f=2
  <= cc4
=> (cc4 (f 4))
  => (f 4) ;; fourth (f 4)
       display f=4
  <= cc5
...so on
  
person marklepp    schedule 21.01.2021