Что возвращает продолжение в схеме?

Я наткнулся на то, чего не могу понять.

#lang scheme

(define cc #f)

(define (val!)
  (call/cc
   (lambda (k)
     (set! cc k)
     0)))

(* 10 (val!))

(cc 100)

Все идет нормально; продолжение (* 10 []) хранится в cc и если мы позвоним (cc 100) мы видим 1000 в REPL, как и ожидалось.

Но затем я попытался определить переменную, которая будет результатом выполнения продолжения:

(define x (cc 20))

я вижу 200 в результате в REPL, но x не определяется

Сохранено ли продолжение в cc включить его возвращение, так что вызов define никогда не возвращается, и вместо этого оценка является результатом (* 10 val)? Что здесь происходит?

2 ответа

В чем дело?

Есть два типа продолжений.

Продолжение, созданное call/ccникогда не возвращает значение своему вызывающему См . Ответ Уилла Несса, чтобы узнать больше.

Но продолжения произведены call-with-composable-continuation являются составными продолжениями, которые возвращают значения.

Решение

Если вы хотите, чтобы продолжение возвращало значение вызывающей стороне, вы должны использовать составное продолжение, настроив приглашение и используя call-with-composable-continuation,

Вы можете определить вид приглашения:

(define my-prompt
  (make-continuation-prompt-tag 'my-prompt))

И используйте подсказку в call-with-composable-continuation указать, что вы хотите захватить только продолжение, начиная с приглашения.

(define cc #f)

(define (val!)
  (call-with-composable-continuation
   (lambda (k)
     (set! cc k)
     0)
   my-prompt))

Затем вам нужно просто поставить подсказку, где вы хотите, чтобы продолжение продолжалось, прежде чем вы позвоните val! чтобы сохранить это.

;; the prompt specifies that it's `(* 10 [])`, and not something larger
(call-with-continuation-prompt
 (λ () (* 10 (val!)))
 my-prompt)

Затем, поскольку у этого продолжения есть четкий "конец", определенный приглашением, он может вернуть значение, когда достигнет этого конца.

(define x (cc 20))
; defines x as 200

Читайте также: Что такое "приглашение к продолжению"?

Он ничего не возвращает, потому что не возвращает. (cc 20), как только (cc 100), не возвращает значение вызывающей стороне. cc это не функция, это продолжение - она ​​сама запоминает, куда возвращать / "кормить" свое значение.

(define x (cc 20))

означает, примерно, в псевдокоде,

(let ([val (cc 20)])
  (primitive-define-top-level-var! "x" val))

но (cc 20) обходит настройку val и используя его для определения x и возвращается непосредственно на верхний уровень, как это было сделано в исходном захваченном продолжении.

Сохранено ли продолжение в cc включите его возвращение [ "destination" - wn], чтобы вызов define никогда не возвращается, и вместо этого оценка является результатом (* 10 val)?

Да.

Что здесь происходит?

Именно это.


редактировать:

Загрузка следующего в DrRacket,

#lang scheme

(define cc #f)
(define (val!)
  (call/cc
   (lambda (k)
     (set! cc k)
     0)))
(* 10 (val!))
(cc 100)
(display "Good!\n")
(define x (cc 20))
(display "Shucks!\n")

Я даже получаю сообщение об ошибке, объясняющее, что происходит:

Язык: схема, с отладкой; ограничение памяти: 128 МБ.
0
1000
Хорошо!
200
define-values: пропущенное определение переменной;
не может продолжаться без определения переменной
переменная: х
в модуле: 'анонимный модуль
>

Другие вопросы по тегам