I saw an example from The Scheme Programming Language, which converts
(letrec ([f (lambda (x) (cons 'a x))]
[g (lambda (x) (cons 'b (f x)))]
[h (lambda (x) (g (cons 'c x)))])
(cons 'd (h '()))) (d b a c)
into CPS
(letrec ([f (lambda (x k) (k (cons 'a x)))]
[g (lambda (x k)
(f x (lambda (v) (k (cons 'b v)))))]
[h (lambda (x k) (g (cons 'c x) k))])
(h '() (lambda (v) (cons 'd v))))
Besides adding an extra parameter for passing continuation to a function, is the function required to make a tail call? The example shows all the converted functions make tail calls, but the text and wikipedia for CPS don't say such a requirement explicitly.
If a function is not required to make a tail call, can we just apply the continuation to the value to be returned in the function body, i.e. if the original value to be returned is expr
, then can we just rewrite it as (k expr)
where k
is the continuation parameter, without further converting it to a tail call?
For example, can g
and h
be rewritten as
g (lambda (x k) (k (cons 'b (f x (lambda (x) x)))))
h (lambda (x k) (k (g (cons 'c x) (lambda (x) x))))
? If it is not acceptable, I guess there might be other ways to not write them to have tail calls?
g
andh
still callk
in tail position. – user4003407