传说中的CPS,颠覆思维的little journey.
First example
(letrec ([f (lambda (x) (cons ‘a x))] [g (lambda (x) (cons ‘b (f x)))] [h (lambda (x) (g (cons ‘c x)))]) (cons ‘d (h ‘())))
We can rewrite this in Continuation-passing style
(letrec([f (lambda (x k) (k (cons ‘a x)))] [g (lambda (x k) (f x (lambda(x) (cons ‘b x))))] [h (lambda (x k) (g (cons ‘c x) k))]) (h ‘() (lambda(x) (cons ‘d x))))
It seems that in CPS every expression are written in the form of procedure application. Actions other than funciotn call are put in C!
CPS allows a procedure to pass more than one result to its continuation
(define car&cdr (lambda(p k) (k (car p) (cdr p)))) (car&cdr ‘(a b c) (lambda(x y) (list y x))) => ((b c) a) (car&cdr ‘(a b c) cons) => (a b c)
Another example is that two continuation is passed. This paradigm could achieve complex control structure.
(define integer-divide (lambda(x y success failure) (if (= y 0) (failure "divide by zero") (let ([q (quotient x y)]) (success q (- x (* q y)))))))
Codes form written with call/cc could now be done with CPS
(define product (let ([break k]) (lambda(ls k) (let f([ls ls] [k k]) (cond [(null? ls) (k 1)] [(= (car ls) 0) (break 0)] [else (f (cdr ls) (lambda(x) (k (* (car ls) x))))])))))
the final example is an interesting CPS map
(define map/k (lambda(p ls k) (if (null? ls) (k ‘()) (p (car ls) (lambda(x) (map/k p (cdr ls) (lambda(y) (k (cons x y))))))))) (define reciprocals (lambda(ls) (map/k (lambda(x k) (if (= x 0) "zero found" (k (/ 1 x)))) ls (lambda(x) x))))
By not passing continuation k to "zero found" this piece actually achieve the effect of Call/cc.
Write a program to automatically transform code to CPS form, unbelievable! Have a try some day.
时间: 2024-10-13 06:36:07