3

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

#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)?到底是怎么回事?

4

2 回答 2

3

它什么也不返回,因为它不返回。(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 MB。
0
1000
好!
200
define-values:跳过变量定义;
  不定义变量变量无法继续
    :模块中的x
    :'anonymous-module

>

于 2017-09-30T19:32:18.910 回答
3

这是怎么回事?

有两种类型的延续。

call/ccnever 生成的延续将值返回给它的调用者。有关更多信息,请参阅Will Ness 的回答

但是由 产生的延续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

另请参阅:“继续提示”到底是什么?

于 2017-09-30T04:45:21.610 回答