3 ms·
What the author is missing: tail recursion in constant space is an implicit requirement for practical use of CPS transformations. In fact this is probably the
by nix 16y ago
What the author is missing: tail recursion in constant space is an implicit requirement for practical use of CPS transformations. In fact this is probably the single biggest reason for wanting efficient tail calls in a language.
ECMA doesn't require efficient tail recursion. Caveat programmer.
- crux_ 16y agoIndeed! You can work around it with a trampoline (http://en.wikipedia.org/wiki/Tail_call#Through_trampolining http://en.wikipedia.org/wiki/Tail_call#Through_trampolining), which is what I did with cfa-js. (http://dl.dropbox.com/u/6600185/cfa/cfademo.html http://dl.dropbox.com/u/6600185/cfa/cfademo.html)
- mattmight 16y agoGood point. True. If you're going to do real CPS programming in JavaScript, you'll want to use a trampoline or a timer mechanism to reset the stack. But, in most cases, you do a little computation and then block waiting for an event. When the continuation gets invoked by the event-handling loop, the stack is reset.
- nix 16y agoWhen the continuation gets invoked by the event-handling loop, the stack is reset. You're not compiling to C here: "the stack" may be a chain of heap-allocated activation records that are still live as far as GC is concerned. What you're describing might work but you'd want to test it to be sure. EDIT: On reflection I agree that the setTimeout() approach should free the stack, however it's implemented.
- masklinn 16y ago> ECMA doesn't require efficient tail recursion. Caveat programmer. You can always use setTimeout to call your tail, which has the neat effect that your CPS "threads" become cooperatively multitasked and can progress alongside each other. Just replace "foo()" tail calls with "setTimeout(foo, 0)". And the downside that you're nuking your stack every time, making debugging quite a bit harder.
- silentbicycle 16y agoCPS is about much more than just callbacks, though.