简体   繁体   English

Scheme中的延续返回是什么?

[英]What does a continuation return in Scheme?

I came across something that I can not understand. 我遇到了一些我无法理解的东西。

#lang scheme

(define cc #f)

(define (val!)
  (call/cc
   (lambda (k)
     (set! cc k)
     0)))

(* 10 (val!))

(cc 100)

So far so good; 到现在为止还挺好; the continuation of (* 10 []) is stored in cc and if we call (cc 100) we see 1000 in the REPL as expected. (* 10 [])的延续存储在cc ,如果我们调用(cc 100)我们会按预期在REPL中看到1000

But the next thing I tried was to define a variable to be the result of running the continuation: 但我接下来尝试的是将变量定义为运行延续的结果:

(define x (cc 20))

I see 200 as a result in the REPL, but x does not get defined. 我在REPL中看到200是结果,但x没有定义。

Does the continuation stored in cc include its returning so that the call to define never returns and instead the evaluation is the result of (* 10 val) ? 存储在cc的continuation是否包含它的返回值,以便define的调用永远不会返回,而评估是(* 10 val) What is going on? 到底是怎么回事?

What's going on? 这是怎么回事?

There are two types of continuations. 有两种类型的延续。

A continuation produced by call/cc never returns a value to its caller. call/cc产生的延续从不向其调用者返回值。 See Will Ness's answer for more on that. 请参阅Will Ness的答案

But the continuations produced by call-with-composable-continuation are composable continuations, which do return values. 但是,通过call-with-composable-continuation continuation产生call-with-composable-continuation可组合的延续,它确实返回值。

The solution 解决方案

If you want a continuation to return a value to its caller, you should use a composable continuation, by setting up a prompt and using call-with-composable-continuation . 如果要继续向其调用者返回值,则应使用可组合的延续,通过设置提示并使用call-with-composable-continuation

You can define a kind of prompt: 您可以定义一种提示:

(define my-prompt
  (make-continuation-prompt-tag 'my-prompt))

And use the prompt in call-with-composable-continuation to specify that you only want to capture the continuation starting from the prompt. 并使用call-with-composable-continuation的提示指定您只想从提示符开始捕获延续。

(define cc #f)

(define (val!)
  (call-with-composable-continuation
   (lambda (k)
     (set! cc k)
     0)
   my-prompt))

Then you just have to put the prompt wherever you want the continuation to start before you call val! 然后你只需要在你打电话给val!之前把提示放在你希望继续的地方val! to save it. 保存它。

;; the prompt specifies that it's `(* 10 [])`, and not something larger
(call-with-continuation-prompt
 (λ () (* 10 (val!)))
 my-prompt)

Then, since this continuation has a clear "end" defined by the prompt, it can return a value when it reaches that end. 然后,由于此延续具有由提示定义的明确“结束”,因此它可以在到达该结束时返回值。

(define x (cc 20))
; defines x as 200

See also: What exactly is a "continuation prompt?" 另请参阅: “持续提示”究​​竟是什么?

It returns nothing, because it does not return. 它什么都不返回,因为它没有返回。 (cc 20) , just as (cc 100) , does not return a value to its caller. (cc 20)正如(cc 100) 将值返回给调用者。 cc is not a function, it is a continuation - it remembers where to return / "feed" its value, by itself. cc不是一个函数,它是一个延续 - 它记住它自己返回/ “提供”其值的位置。

(define x (cc 20))

means, approximately, in pseudocode, 大概是指伪代码,

(let ([val (cc 20)])
  (primitive-define-top-level-var! "x" val))

but (cc 20) bypasses the setting of val and using it to define x , and returns directly to the top level, as was done by the original captured continuation. 但是(cc 20)绕过val的设置并使用它来定义x ,并直接返回到顶层,就像原始捕获的延续一样。

Does the continuation stored in cc include its returning [ "destination" -- wn] so that the call to define never returns and instead the evaluation is the result of (* 10 val) ? 存储在cc的continuation是否包含其返回的[ “destination” - wn],以便define的调用永远不会返回,而评估是(* 10 val)

Yes. 是。

What is going on? 到底是怎么回事?

Exactly that. 确切地说。


edit: 编辑:

Loading the following in DrRacket, 在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")

I even get an error message explaining what is going on: 我甚至收到一条错误消息,解释发生了什么:

Language: scheme, with debugging; 语言:方案,调试; memory limit: 128 MB. 内存限制:128 MB。
0 0
1000 1000
Good! 好!
200 200
define-values: skipped variable definition; define-values:跳过的变量定义;
cannot continue without defining variable 没有定义变量就无法继续
variable: x 变量:x
in module: 'anonymous-module 在模块中:'匿名模块
> >

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM