Scheme 计划中的延续回报是什么?

Scheme 计划中的延续回报是什么?,scheme,racket,continuations,delimited-continuations,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 但接下来我尝试定义一个变量作为运行continuation的结果: (define x (cc 20))

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

#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

但接下来我尝试定义一个变量作为运行continuation的结果:

(define x (cc 20))
我在REPL中看到了
200
,但是
x
没有定义

存储在
cc
中的continuation是否包含其返回,以便对
define
的调用永远不会返回,而是由
(*10 val)
的结果进行计算?发生了什么事?

发生了什么事? 有两种类型的延续

由生成的延续从不向其调用者返回值。更多信息请参见

但是由生成的continuations是可组合的continuations,它确实返回值

解决方案 如果希望继续向其调用者返回值,则应使用可组合的继续,方法是设置提示并使用

您可以定义一种提示:

(define my-prompt
  (make-continuation-prompt-tag 'my-prompt))
并使用中的提示指定只希望捕获从提示开始的延续

(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
中的continuation是否包含其返回[“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 MB。
0
1000
好!
200
定义值:跳过变量定义
如果不定义变量,则无法继续
变量:x
模块中:“匿名模块
>


如果您想让continuations返回值,应该使用composable continuations,方法是设置一个提示符并使用带有composable continuation的
调用。当然,如果您想将代码包装在
中,让
在表达式之间没有continuation障碍,您将看到它变成了一个无限循环,执行
(*10 20)
@sylvester我无法理解你的评论。你能展示你提到的完整代码吗?我的代码只是一个伪代码。只需将整个顶级表达式包装在
(let())
中,你就永远不会得到“Good!\n”输出,因为前一行跳回
(*10 100)
每次。R5RS中没有指定定义的行为,这是PLTs
#lang scheme
应该遵循的。感谢您的澄清。当然,这是“有意义的”,因为
let
有一个隐式的
begin
@sylvester
#lang scheme
名称不好;它不遵循任何方案标准。它是PLT方案时代的遗留物,本质上是
#lang racket
。只有
#lang r5rs
遵循r5rs。