Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continuation passing style - function composition

I'm learning about CPS with Racket, and I've managed to write up these functions:

;lift a regular single-arg function into CPS
(define (lift/k f)
  (lambda (x k)
    (k (f x))))

;compose two CPS functions
(define (compose/k f g)
  (lambda (x k)
    (g x (lambda (y)
           (f y k)))))

They seem to work correctly

(define (is-two/k x k)
  (k (= x 2)))
(define is-not-two/k (compose/k (lift/k not) is-two/k))
(is-not-two/k 3 display)
(is-not-two/k 2 display)

#t#f

I'm wondering if these functions are still "true CPS". Have I messed up "true" continuation-passing with these functions? Is it kosher to use function composition techniques in CPS? Is it encouraged? Or would it be considered a "compromise" to do this? Is there a more CPS-y way to do it?

Yes I know I just asked 5 questions, but the basic idea behind them all (which I'm not sure I understand correctly) is the same. Explanations in other Lisps, Haskell, Erlang, or other functional languages are fine.

like image 326
Dan Burton Avatar asked Jan 21 '23 07:01

Dan Burton


1 Answers

The continuation-passing-style transform can be partial, or complete. You're usually working with a system where certain primitives (+, -, etc.) are stuck in non-cps-land. Fortunately, CPS works fine either way.

The steps in CPSing:

  • Pick which functions are going to be primitive.
  • CPS-transform so that all non-primitive functions (including continuations) are called only in tail position.

So, in your code, your 'lift/k' is essentially treating its given function as being primitive: note that the body of lift/k calls 'f' in non-tail position. If you want not to treat the lifted function as a primitive, you must go in and rewrite it explicitly.

Your 'compose' function composes two CPSed functions, but is not itself in CPS (that is, you're assuming that 'compose' is primitive. You probably want to CPS it. Note that since it just returns a value straight off, this is simple:

;compose two CPS functions
(define (compose/k f g k)
  (k (lambda (x k)
       (g x (lambda (y)
              (f y k))))))
like image 162
John Clements Avatar answered Jan 28 '23 05:01

John Clements