# CS 536: Programming Language Concepts Examples of CPS

To CPS-convert a cond statement:

• If the questions are all tail calls, send the answer of each cond-clause to the continuation k, then check whether the new answer expressions have any tail calls. Convert as needed.

• If a question has a non-tail call, pull the call outside the cond and replace the question with the box (the arg to the lambda). Then continue the conversion as before.

### Examples

• ```(define (rect-area w h)
(* w h))
(+ (rect-area 10 8) 3)

==>

(define (rect-area/k w h k)
(k (* w h)))

(rect-area/k 10 8 (lambda (v) (+ v 3)))
```
• ```(define (g x) (* x 6))
(define (h y) (+ y 5))
(+ 4 (g (h 3)))

[hint: convert to using h/k and g first, then to h/k and g/k]

==>

(define (g/k x k)
(k (* x 6)))

(define (h/k y k)
(k (+ y 5)))

(h/k 3 (lambda (v1) (+ 4 (g v1))))

==>

(h/k 3 (lambda (v1) (g/k v1 (lambda (v2) (+ 4 v2)))))
```
• ```(define (foo y) (+ (h (* y 2)) 7)) [h from above]
(foo 8)

==>

(define (foo/k y k) (k (+ (h (* y 2)) 7))) [h from above]

==>

(define (foo/k y k) (h/k (* y 2) (lambda (v) (k (+ v 7)))))
(foo/k 8 (lambda (x) x))
```
• ```(define (sum-area w1 h1 w2 h2)
(+ (rect-area w1 h1)
(rect-area w2 h2)))

(sum-area 2 4 6 8)

==>

(define (sum-area/k w1 h1 w2 h2 k)
(rect-area/k w1 w2 (lambda (vleft) (k (+ vleft (rect-area w2 h2))))))

==>

(define (sum-area/k w1 h1 w2 h2 k)
(rect-area/k w1 h1 (lambda (vleft)
(rect-area/k w2 h2 (lambda (vright)
(k (+ vleft vright)))))))

(sum-area 2 4 6 8 (lambda (x) x))

[note that we have "linearized" the "tree-like" calls to rect-area]
```
• ```(define (product alon)
(cond [(empty? alon) 1]
[(cons? alon) (* (first alon) (product (rest alon)))]))

==>

(define (product/k alon k)
(cond [(empty? alon) (k 1)]
[(cons? alon) (k (* (first alon) (product (rest alon))))]))

==>

[convert the non-tail call in the cons? answer]

(define (product/k alon k)
(cond [(empty? alon) (k 1)]
[(cons? alon) (product/k (rest alon)
(lambda (box)
(k (* (first alon) box))))]))

```
• ```(define (filter pred L)
(cond [(empty? L) empty]
[(cons? L)
(cond [(pred (first L)) (cons (first L) (filter pred (rest L)))]
[else (filter pred (rest L))])]))

==>

(define (filter/k pred L k)
(cond [(empty? L) (k empty)]
[(cons? L)
(k (cond [(pred (first L)) (cons (first L) (filter pred (rest L)))]
[else (filter pred (rest L))])])))

==>

[pull up the non-tail call in the question (pred (first L))]

(define (filter/k pred/k L k)
(cond [(empty? L) (k empty)]
[(cons? L)
(pred/k (first L)
(lambda (predval)
(k (cond [predval (cons (first L) (filter pred (rest L)))]
[else (filter pred (rest L))]))))]))

==>

[send both answers of hte inner cond to k]

(define (filter/k pred/k L k)
(cond [(empty? L) (k empty)]
[(cons? L)
(pred/k (first L)
(lambda (predval)
(cond [predval (k (cons (first L) (filter pred (rest L))))]
[else (k (filter pred (rest L)))])))]))

==>

[work the k into both answer expressions]

(define (filter/k pred/k L k)
(cond [(empty? L) (k empty)]
[(cons? L)
(pred/k (first L)
(lambda (predval)
(cond [predval
(filter/k pred/k (rest L)
(lambda (box) (k (cons (first L) box))))]
[else (k (filter pred (rest L)))])))]))

==>

(define (filter/k pred/k L k)
(cond [(empty? L) (k empty)]
[(cons? L)
(pred/k (first L)
(lambda (predval)
(cond [predval
(filter/k pred/k (rest L)
(lambda (box) (k (cons (first L) box))))]
[else (filter/k pred/k (rest L) k)])))]))

```

 This page maintained by Kathi Fisler Department of Computer Science Worcester Polytechnic Institute