5 ms·
If you generalize labels so that they become first class, then call/cc can be written in terms of goto. http://ssp.impulsetrain.com/goto.html http://ssp.impulse
by ssp 12y ago
If you generalize labels so that they become first class, then call/cc can be written in terms of goto. http://ssp.impulsetrain.com/goto.html http://ssp.impulsetrain.com/goto.html
- WallWextra 12y agoIt's longjmp.
- mostly_harmless 12y agonot quite. It is similar to longjmp except that this can jump down the stack. these labels can be jumped to even after the function returns
- lisper 12y agoRight. The way it was explained to me years ago that really stuck with me is that one way to implement call/cc is to copy the stack onto the heap. (And another way to do it is to simply allocate all your function call frames on the heap to begin with and not have a stack. Then call/cc is essentially free, but you need a really good incremental garbage collector because now every function call conses.)
- ssp 12y agoDoes copying the stack really work? What if some local variable changes in between the call/cc and calling the continuation? If the stack is a copy, that change will not be reflected when the continuation runs.
- lisper 12y agoThat's a very interesting point. AFAICT, the Scheme standard doesn't actually say what should happen in this case. But here's what e.g. Chibi scheme does: > (let ((x 0)) (list (call/cc (lambda (f) (set! x 1) (f 2))) x)) (2 0)
- ssp 12y agoThe equivalent in Oort produces: localhost:~/oort/examples% ../oort callcc2.nl 2 1 as expected since Oort uses heap allocated activation records. The Oort program: typedef continuation_t = fn (p: int32) -> void; call_cc (fun: fn(k: continuation_t) -> void) -> int32 { retval: int32; fun (fn (v: int32) -> void { retval = v; goto current_continuation; }); // If fun returns without calling the continuation, // then just return 0 return 0; @current_continuation: return retval; } x: int32 = 0; print call_cc (fn (k: continuation_t) { x = 1; k (2); }); print x;