user3597931
user3597931

Reputation:

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?

Upvotes: 3

Views: 864

Answers (2)

Alex Knauth
Alex Knauth

Reputation: 8373

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

Upvotes: 3

Will Ness
Will Ness

Reputation: 71119

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

>

Upvotes: 3

Related Questions