Reputation:
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
Reputation: 8373
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.
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
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 todefine
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