lang racket
;阶乘函数最初版本
(define (fact-i1 n)
(if(= n 0)
1
(* n (fact-i1 ( - n 1)))))
;调用很正常
;尾递归版本(但是这里不深入探讨)
(define (fact-i2 n result)
(if (= n 1)
result
(fact-i2 (- n 1) (* n result))))
;调用方式为(fact-i2 6 1)result必须传入1
;传入自己的版本
(define (fact self n)
(if(= n 0)
1
(* n (self self (- n 1)))))
;调用方式为:(fact fact 5),但是此时函数中已经没有自己的名字了。
;将fact柯里化后
(define fact2
(lambda (self)
(lambda (n)
(if (= n 0)
1
(* n ((self self) (- n 1)))))))
;柯里化后的调用约定是((f x) y)
;因此为了和函数头调用相对应,递归的第二次调用应该是(selfself)
;调用方式为((fact2 fact2)5)
;将fact2的参数互换位置后
(define fact3
(lambda (n)
(lambda (self)
(if (= n 0)
1
(* n ((self (- n 1)) self))))))
;调用方式为:((fact3 5)fact3)
;非自身情况的调用1
(define fact4
(lambda (n)
(lambda (self)
(if (= n 0)
1
(* n (self self (- n 1)))))))
;调用方式为:((fact4 6)fact)
;非自身情况的调用2
(define fact5
(lambda (self)
(lambda (n)
(if (= n 0)
1
(* n (self (- n 1)))))))
;self n时,((fact5 fact-i1) 5)
;n self时,((fact5 5) fact-i1)
;超级版本
;实际上是fact2的展开,fact2要去掉fact2后的产物,是穷人版的Y组合子。
(define factorial
((lambda (self1)
(lambda (n)
(if (= n 0)
1
(* n ((self1 self1)(- n 1))))))
(lambda (self2)
(lambda (n)
(if (= n 0)
1
(* n ((self2 self2)(- n 1))))))))
;调用方式:(factorial 6)
;Y 组合子
(define Y1
(lambda (F)
((lambda (self)
(F (lambda (x) ((self self) x))))
(lambda (self)
(F (lambda (x) ((self self) x)))))))
(define Y2
(lambda (F)
((lambda (x) (x x))
(lambda (self)
(F (lambda (x) ((self self) x)))))))
;Y2就是Y1的展开
(define (Fib-maker f)
(lambda (n)
(if (<= n 1)
1
(+ (f (- n 1))
(f (- n 2))))))
(define (A f)
(lambda (x)
(lambda (y)
(cond [(= y 0) 0]
[(= x 0) (* 2 y)]
[(= y 1) 2]
[else ((f (- x 1)) ((f x) (- y 1)))]))))
;A需要这样写
(define fib (Y1 Fib-maker))
(fib 5)
(define aa (Y2 A))
((aa 3) 2)
;尾递归版本的
(define fact
(lambda (f)
(lambda (n)
(lambda ([result 1])
(if (= n 1)
result
(((f f) (- n 1)) (* n result)))))))
(((fact fact) 6) 1)
(define fac
((lambda (f)
(lambda (n [result 1])
(if (= n 1)
result
((f f) (- n 1) (* n result)))))
(lambda (f)
(lambda (n [result 1])
(if (= n 1)
result
((f f) (- n 1) (* n result)))))))
(fac 6)