Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifics of call/cc

This is related to What is call/cc?, but I didn't want to hijack this question for my own purposes, and some of its arguments like the analogy to setjmp/longjmp evade me.

I think I have a sufficient idea about what a continuation is, I think of it as a snapshot of the current call stack. I don't want to go into the discussion why this might be interesting or what you can do with continuations. My question is more specifically, why do I have to provide a function argument to call/cc? Why doesn't call/cc just return the current continuation, so I could do whatever I please with it (store it, call it, you name it)? In a link from this other question (http://community.schemewiki.org/?call-with-current-continuation-for-C-programmers), it talks about "Essentially it's just a clean way to get the continuation to you and keep out of the way of subsequent jumps back to the saved point.", but I'm not getting it. It seems unnecessarily complicated.

like image 737
ThomasH Avatar asked Jul 13 '09 14:07

ThomasH


2 Answers

If you use a construct like Jay shows, then you can grab the continuation, but in a way, the value that is grabbed is already spoiled because you're already inside that continuation. In contrast, call/cc can be used to grab the continuation that is still pending outside of the current expression. For example, one of the simplest uses of continuations is to implement a kind of an abort:

(call/cc (lambda (abort)
           (+ 1 2 (abort 9))))

You cannot do that with the operation you describe. If you try it:

(define (get-cc) (call/cc values))
(let ([abort (get-cc)]) (+ 1 2 (abort 9)))

then you get an error about applying 9 as a procedure. This happens because abort jumps back to the let with the new value of 9 -- which means that you're now doing a second round of the same addition expression, except that now abort is bound to 9...

Two additional related notes:

  1. For a nice an practical introduction to continuations, see PLAI.
  2. call/cc is a little complex in that it takes in a function -- a conceptually easier to use construct is let/cc which you can find in some implementations like PLT Scheme. The above example becomes (let/cc abort (+ 1 2 (abort 9))).
like image 122
Eli Barzilay Avatar answered Nov 10 '22 21:11

Eli Barzilay


That would be less versatile. If you want that behavior, you can just do:

(call/cc (lambda (x) x))

You could take a look at the example usages of continuations in "Darrell Ferguson and Dwight Deugo. "Call with Current Continuation Patterns". 8th Conference on Pattern Languages of Programs. September 2001." (http://library.readscheme.org/page6.html) and try to rewrite them using a call/cc-return, defined as above.

like image 39
Jay Kominek Avatar answered Nov 10 '22 22:11

Jay Kominek