简体   繁体   中英

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.

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.

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) ? 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. See Will Ness's answer for more on that.

But the continuations produced by call-with-composable-continuation are composable continuations, which do return values.

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 .

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.

(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! 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 is not a function, it is a continuation - it remembers where to return / "feed" its value, by itself.

(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.

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

Yes.

What is going on?

Exactly that.


edit:

Loading the following in 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.
0
1000
Good!
200
define-values: skipped variable definition;
cannot continue without defining variable
variable: x
in module: 'anonymous-module
>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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