Call Features / cc

This is due to What is call / cc? , but I didnโ€™t want to carry this issue for my own purposes, and some of its arguments, like the setjmp / longjmp analogy bypassed me.

I think that I have a good idea of โ€‹โ€‹what the continuation is, I think of it as a snapshot of the current call stack. I don't want to discuss why this might be interesting or what you can do with sequels. My question is more specifically, why should I provide a function argument for calling / cc? Why doesn't call / cc just return the current continuation, so I could do whatever I wanted (store it, call it, call it)? A link from this other question ( http://community.schemewiki.org/?call-with-current-continuation-for-C-programmers ) says: "Essentially, this is just a clean way to get continued for you and don't leave the paths of subsequent jumps back to the saved point. ", but I do not understand. It seems overly complicated.

+7
continuations scheme callcc
source share
4 answers

Against the general SO netiquette, I answer my question, but more as an editor than an answer provider.

After some time, I started a similar question in LtU . In the end, these are the guys who ponder the design of the language all day, aren't they, and one of the answers finally hired me, Now the things mentioned here, for example. Eli, or in the original question, makes much more sense to me. It is all about what is included in the sequel, and where the applied continuation is applied.

One of the posters in LtU wrote:

โ€œYou can see exactly how call / cc allows you toโ€œ stay away. โ€With em or get / cc you need to do some kind of test to determine if you have reverse gear or just the initial one. Basically, call / cc saves the use of the continuation from the continuation, whereas with get / cc or em the continuation contains its use and therefore (usually) you need to add a test to the beginning of the continuation (that is, immediately after get / cc / em) to separate the "use of parts of the continuation "from parts" of the rest of the sequel. "

This brought him home for me.

Thanks guys anyway!

+2
source share

If you use a construction similar to the Jay show, then you can capture the sequel, but in some way the value that is captured is already corrupted because you are already in this sequel. In contrast, call/cc can be used to capture a continuation that is still outside the current expression. For example, one of the simplest uses of continuations is to implement a kind of abort :

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

You cannot do this with the operation you described. If you try:

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

then you will receive an error message about using 9 as a procedure. This is because abort returns to let with a new value of 9 - this means that you are now performing the second round of the same add expression, except that abort now bound to 9 ...

Two additional notes:

  • For a pleasant practical introduction, see PLAI .
  • call/cc is a bit complicated in what it takes in functions - it is conceptually easier to use the let/cc construct, which you can find in some implementations, such as the PLT Scheme. The above example becomes (let/cc abort (+ 1 2 (abort 9))) .
+9
source share

That would be less universal. If you want this behavior, you can simply do:

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

You can take a look at an example of using continuations in "Darrell Ferguson" and "Dwight Deugo". "Call with Current Continuation Patterns." 8th Conference on Program Template Languages. September 2001 ( http://library.readscheme.org/page6.html ) and try rewriting them using the / cc -return call defined above.

+2
source share

I suggest starting with the question: what does it mean to be a first-class continuation?

A continuation of an expression essentially consists of two pieces of data: first, the closure (that is, the environment) of that expression; and secondly, an idea of โ€‹โ€‹what should be done with the result of the expression. Thus, a first-class continuation language is one that has data structures that encapsulate these parts, and that processes these data structures just like any other.

call / cc is a particularly elegant way to implement this idea: the current sequel is packaged as a procedure that encapsulates what needs to be done using an expression, like what the procedure does when applied to an expression; to represent a continuation in this way simply means that closing this procedure contains the environment on the site to which it was called.

You could imagine realizing the idea of โ€‹โ€‹first-class continuations in other ways. They will not call / cc, and itโ€™s hard for me to imagine how such a presentation could be simpler.

In the split note, consider the let / cc implementation mentioned by Eli, which I prefer to call bind / cc:

 (define-syntax bind/cc (syntax-rules () ((bind/cc var . body) (call/cc (lambda (var) . body))))) 

And as an exercise, how would you implement call / cc based on bind / cc?

+2
source share

All Articles