【问题标题】:What does a continuation return in Scheme?Scheme 中的持续回报是什么?
【发布时间】:2018-03-11 22:43:16
【问题描述】:

我遇到了一些我无法理解的东西。

#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) 的结果?怎么回事?

【问题讨论】:

  • 如果您希望延续返回值,您应该使用可组合延续,方法是设置提示并使用call-with-composable-continuation

标签: scheme racket continuations delimited-continuations


【解决方案1】:

它什么也不返回,因为它不返回。 (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 中的延续是否包括其返回的 ["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
在模块中:'匿名模块

>

【讨论】:

  • 当然,如果您将代码包装在 let 中,这样您在表达式之间就没有连续障碍,您会看到它变成了一个无限循环,执行 (* 10 20)
  • @Sylwester 我无法理解您的评论。你能展示你提到的完整代码吗?我的只是一个伪代码。
  • 只需将整个顶级表达式包装在 (let () ...) 中,您将永远不会得到“Good!\n”输出,因为上一行每次都跳回 (* 10 100)define 的行为未在 R5RS 中指定,这是 PLT #lang scheme 应该遵循的。
  • 感谢您的澄清。当然,这是“有道理的”,因为let 有一个隐含的begin
  • @Sylwester #lang scheme 名字不好;它不遵循任何方案标准。它是 PLT Scheme 时代的遗留物,本质上是#lang racket。只有#lang r5rs 跟随R5RS。
【解决方案2】:

发生了什么事?

有两种类型的延续。

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?"

【讨论】:

    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    • 2012-05-25
    • 1970-01-01
    • 2016-11-01
    相关资源
    最近更新 更多