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。