Marco Faustinelli
Marco Faustinelli

Reputation: 4216

How to start captured current continuations in Racket

I am studying call/cc in Racket along the lines of paper Continuations by example: Exceptions, time-traveling search, generators, threads, and coroutines 1.

The paper mentions that the most advantageous API is derived from call/cc by providing a procedure lambda (cc) (cc cc). I understand this specific call/cc invocation returns the current continuation first-class object to the main program.

In the example that follows, the paper calls all this (right-now).

What I see is that inside that same example the cc object returned by the abovementioned call/cc invocation is always run afterwards by applying it to itself. That's what I don't understand.

I don't see what is so special in cc as value, so I have tried to start it as a function with (cc ()), or (cc (lambda () ())), or even (cc "whatever") and (cc). No joy whatsoever: apparently the continuation wants just that application to itself in order to start to run.

Why is that? What is an example that clearly illustrates the uniqueness of running cc's by doing (cc cc) ?

Upvotes: 3

Views: 254

Answers (1)

soegaard
soegaard

Reputation: 31145

In

(let ((cc (current-continuation)))
  ...)

The continuation of (current-continuation) is

(lambda (_)
  (let ((cc _))
    ...)

Call this continuation c0.

The definition of current-continuation is:

(define (current-continuation)
  (call/cc (lambda (cc) (cc cc))))

So call/cc calls (lambda (cc) (cc cc)) with c0 as argument:

  ((lambda (cc) (cc cc)) c0)
= (c0 c0)

Inserting the value of c0:

((lambda (_)
   (let ((cc _))
     ...)
 c0)

which becomes:

   (let ((cc c0))
     ...)

Which means that inside ... the identifier cc is now bound to the value c0.

If (c0 42) occurs in the ...

The we get:

   (c0 42)
= ((lamdba (_)
     (let ((cc _))
      ...)
   42)
= (let ((cc 42))
     ...)

And now cc is bound to the value 42.

The example uses (procedure? cc) and (future-value? cc) to test whether cc is bound to the continuation (if (procedure? cc) is true) and or another value (the future value is here 42).

So in:

(define (current-continuation)
  (call/cc (lambda (cc) (cc cc))))

the value passed to (lambda (cc) (cc cc))) is the continuation. If we want to our hands on it, we need to return it and we do that by passing it to the continuation. I.e. (cc something) will return something, and since we want to get the continuation itself we use (cc cc).

Upvotes: 2

Related Questions