1
votes

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?

1
Your rewritten g and h still call k in tail position.user4003407

1 Answers

0
votes

When transforming scheme code into continuation passing style every procedure call becomes a tail call.