我遇到了一些我无法理解的事情。
#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)
的结果?发生了什么事?
答案 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
答案 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
>