Scheme中的延续返回是什么?

时间:2017-09-30 01:38:48

标签: scheme racket continuations delimited-continuations

我遇到了一些我无法理解的事情。

#lang scheme

(define cc #f)

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

(* 10 (val!))

(cc 100)

到目前为止一切顺利; (* 10 [])的延续存储在cc中,如果我们致电(cc 100),我们会按预期在REPL中看到1000

但我接下来尝试的是将变量定义为运行延续的结果:

(define x (cc 20))

我在REPL中看到200,但x未定义。

cc中存储的延续是否包含其返回,以便对define的调用永远不会返回,而评估是(* 10 val)的结果?发生了什么事?

2 个答案:

答案 0 :(得分:3)

发生了什么?

有两种类型的延续。

call/cc生成的延续从不向其调用者返回值。有关详情,请参阅Will Ness's answer

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

另请参阅:What exactly is a "continuation prompt?"

答案 1 :(得分:3)

它什么都不返回,因为它没有返回。 (cc 20),就像(cc 100)一样,会向其调用者返回一个值。 cc不是一个函数,它是一个延续 - 它会记住 返回/ “feed”其值的位置。

(define x (cc 20))

大约是指伪代码,

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

但是(cc 20)会绕过val的设置,并使用它来定义x,并直接返回到顶层,就像原始捕获的延续一样。

  

cc中存储的延续是否包含其返回的[“目标” - 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 MB   0
  1000
  好!
  200个
   define-values:跳过的变量定义;
   如果没有定义变量,就无法继续    变量:x
   在模块中:'anonymous-module

  >