I've recently started learning Scheme, and have written a function to compute factorials using CPS:
(define (fact-cps n k)
(if (<= n 1)
(k 1)
(fact-cps (- n 1)
(lambda (r)
(k (* n r))))))
I know that call/cc can construct the continuation of current expression, which should avoid explicitly passing the continuation parameter k in the function. I'm not quite sure how to do this, though; can you give any hints?
I think you misunderstand what
call/ccdoes. Imagine you write the code(+ (* 2 3) (* 4 5)). The order of execution of(* 2 3)and(* 4 5)is not known since the implementation can do it any way. A Scheme that does CPS-conversions might make something like this:So imagine instead of
5we have(call/cc (lambda (k) (k 33))). It will force the first*&to never happen and rather just call the continuation with33as the first multiplication.In this regard you can use the argument
call/ccfunction gets, aka the continuation, as a goto that you have available even though you don't write in CPS style. Eg. this is typical:Without
call/ccyou'll need avoid filling the stack by making nested continuations for the default and rather throw these in the situation where we have odd elements. Of course, it's just as simple todo 2 passes where the first one just counts the elements. The big O would be the same and doing it in one pass can be thought of as micro optimization.