cps continuation passing style

#lang racket
;(h i (lambda (hi) ...)) We assume that hi is
;the result of applying (h i). Then, we drop in everything else that
;has to be done to replace the ...:

;(f (g (h i) (j l)))

;becomes

;(h i (lambda (hi) (f (g hi (j l)))))


;rember方法
;普通方式
(define rember8
  (lambda (ls)
    (cond
      [(null? ls) '()]
      [(= (car ls) 8) (cdr ls)]
      [else (cons (car ls) (rember8 (cdr ls)))])))

(rember8 '(1 2 8 3 4 6 7 8 5))


;第一步,参数中添加一个k
;whenever we see a lambda in the code we want to CPS, we
;have to add an argument, and then process the body

;(define rember8
;  (lambda (ls k)
;    (cond
;      [(null? ls) '()]
;      [(= (car ls) 8) (cdr ls)]
;      [else (cons (car ls) (rember8 (cdr ls)))])))

;第二步,不要为小事费力
;Second rule: "Don't sweat the small stuff!"

;Small stuff is stuff we know will terminate right away.

;Don't sweat the small stuff if we know it will be evaluated.

;Don't sweat the small stuff if it *might* be evaluated, but instead
;pass it to k.

;cond的第一个分支
;(null? ls)为will terminate right away,所以不用管
;'()为*might* be evaluated,所以传递给k
;(define rember8
;  (lambda (ls k)
;    (cond
;      [(null? ls) (k '())]
;      [(= (car ls) 8) (cdr ls)]
;      [else (cons (car ls) (rember8 (cdr ls)))])))


;cond的第二个分支,传递给k
;(define rember8
;  (lambda (ls k)
;    (cond
;      [(null? ls) (k '())]
;      [(= (car ls) 8) (k (cdr ls))]
;      [else (cons (car ls) (rember8 (cdr ls)))])))

;cond的第三个分支,需要创建一个新的continuation
;(define rember8
;  (lambda (ls k)
;    (cond
;      [(null? ls) (k '())]
;      [(= (car ls) 8) (k (cdr ls))]
;      [else (rember8 (cdr ls) (lambda (x) (cons (car ls) x)))])))

;将新的continuation pass to k
;将新的continuation与老的continuation即k,连接起来
(define rember8-cps
  (lambda (ls k)
    (cond
      [(null? ls) (k '())]
      [(= (car ls) 8) (k (cdr ls))]
      [else (rember8-cps (cdr ls) (lambda (x) (k (cons (car ls) x))))])))

;第四步,确定k为什么
;当ls为空list的时候,普通rember8的返回值应该为空list,即cps的rember8中(k '())的值为'(),所以k为identity function
(rember8-cps '(1 2 8 3 4 6 7 8 5) (lambda (x) x))


;普通multirember8
(define multirember8
  (lambda (ls)
    (cond
      [(null? ls) '()]
      [(= (car ls) 8) (multirember8 (cdr ls))]
      [else (cons (car ls) (multirember8 (cdr ls)))])))

(multirember8 '(1 2 8 3 4 6 7 8 5))

;转换为cps的形式
(define multirember8-cps
  (lambda (ls k);参数添加k
    (cond
      [(null? ls) (k '())];返回值传递给k
      [(= (car ls) 8) (multirember8-cps (cdr ls) k)] ;透传函数
      [else (multirember8-cps (cdr ls) (lambda (x)
                                     (k (cons (car ls) x))))])));添加一个新的continuation,并传递给k

;最后一步,确定k的函数
;ls为空时,返回值为空list,所以k为(lambda (v) v)
(multirember8-cps '(1 2 8 3 4 6 7 8 5) (lambda (v) v))


;非尾递归
(define fact
  (lambda (n)
    (cond
      [(zero? n) 1]
      [else (* (fact (- n 1)) n)])))

(fact 5)

;尾递归
;;aps
;;accumulator-passing style
(define fact-aps
  (lambda (n acc)
    (cond
      [(zero? n) acc]
      [else (fact-aps (sub1 n) (* acc n))])))

(define fact2
  (lambda (n)
    (fact-aps n 1)))

(fact2 5)


;;cps
(define fact-cps
  (lambda (n k)
    (cond
      [(zero? n) (k 1)] ;;当n为0的时候,我们给continuation的东西为1
      [else (fact-cps (sub1 n)    ;;我们需要创建一个新的continuation,代表剩下的计算
                      (lambda (v) ;;此时,我们给到continuation的东西为什么,新的continuation传递给老的continuation k
                        (k (* v n))))])))

(fact-cps 5 (lambda (v) v))
(fact-cps 5 (lambda (v) (* 3 v)))


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值