Как проанализировать эквивалентный получатель в вызове / cc? - PullRequest
1 голос
/ 27 апреля 2020

Я читаю книгу Схема и искусство программирования , но не могу придумать ответ на следующий вопрос:

Если r равно

(escaper (lambda (continuation) (continuation body))

в (... (call/cc r) ...), когда r можно переписать как

(lambda (continuation) body)

1 Ответ

2 голосов
/ 27 апреля 2020

Ответ: всегда .

escaper не является частью Схемы. Он определяется этой книгой, Схема и искусство программирования , таким образом:

"escaper превращает процедуру аргумента в аналогично определенную процедуру 'escape' ( он же «продолжение»), который, когда вызывается, его результат становится результатом всего вычисления. Все, что ожидает результата [вызова этой escape-процедуры], игнорируется ». (слегка отредактировано)

Результат (continuation body) в версии "escaper -ed" (lambda (c..n) (c..n body)) будет возвращено непосредственно на верхний уровень, за исключением того, что continuation не не возвращает . Он переходит в его целевой контекст (1), то есть , то , который ожидает результата вызова (call/cc r), потому что this continuation устанавливается этим вызовом на call/cc:

           ;; (0)   -- top level
             (... 
                  ;; (1)  <-----------------------------------\
                    (call/cc r)  ;; r = (escaper (lambda (continuation)
                                 ;;                 (continuation body)))
                         ...)
===
           ;; (0)   -- top level
             (... 
                  ;; (1)  
                    (continuation--0                       ;; set up by `escaper`
                      ((lambda (continuation)
                            (continuation body))
                        continuation--1))                   ;; set up by call/cc
                         ...)
===
           ;; (0)   -- top level
             (... 
                  ;; (1)  
                    (continuation--0
                       (let ((continuation continuation--1))   ;; by application of `lambda`
                         (continuation body)))
                         ...)

Так что если body возвращает , этот результат передается в (1) на continuation--1; и если body вызывает continuation со значением, это значение передается в (1) с помощью continuation--1. Ничего не возвращается к continuation--0, поэтому его скачок никогда не срабатывает.

И в

           ;; (0)
             (... 
                  ;; (1)
                    (call/cc (lambda (continuation) body))
                         ...)
===
           ;; (0)
             (... 
                  ;; (1)
                    (let ((continuation continuation--1)) 
                       body)
                         ...)

происходит точно то же самое: если body возвращает , этот результат просто возвращается в (1); и если body вызывает continuation со значением, это значение передается в (1) с помощью continuation--1.

...