Exercise 1.43. If f is a numerical function and n is a positive integer, then we can form the nth repeated application of f, which is defined to be the function whose value at x is f(f(...(f(x))...)). For example, if f is the function x x + 1, then the nth repeated application of f is the function x x + n. If f is the operation of squaring a number, then the nth repeated application of f is the function that raises its argument to the 2nth power. Write a procedure that takes as inputs a procedure that computes f and a positive integer n and returns the procedure that computes the nth repeated application of f. Your procedure should be able to be used as follows:
((repeated square 2) 5)
625
Hint: You may find it convenient to use compose from exercise 1.42.
在不借用练习 1.42 的基础上,写递归 repeated 过程时需要保持清醒的头脑,告诉自己 repeated 过程是返回另外一个过程的,并且要考虑好终止条件是在 times = 0 还是 times = 1 的时候。迭代的 repeated 思路上比递归的要直接一些。当借用了练习 1.42 的 compose 的时候,写递归的 repeated 思路变得清晰很多,compose 作为一种粘合剂可以把 f 和 repeated 给粘合起来。
(define (repeated f times)
(lambda (x)
(cond ((= times 0) x)
(else
((repeated f (- times 1))
(f x))))))
(define (repeated/iter f times)
(define (iter current-time result)
(cond ((> current-time times) result)
(else
(iter (+ current-time 1) (f result)))))
(lambda (x)
(iter 1 x)))
; with compose as glue
(define (repeated/compose f times)
(cond ((= times 0) (lambda (x) x))
(else
(lambda (x)
(f ((repeated/compose f (- times 1)) x))))))
然后进行三个 repeated 过程的测试,注意测试 times = 0 的情况!
(assert= ((repeated square 0) 5) 5)
(assert= ((repeated/iter square 0) 5) 5)
(assert= ((repeated/compose square 0) 5) 5)
(assert= ((repeated square 1) 5) 25)
(assert= ((repeated/iter square 1) 5) 25)
(assert= ((repeated/compose square 1) 5) 25)
(assert= ((repeated square 2) 5) 625)
(assert= ((repeated square 2) 5)
((repeated/iter square 2) 5))
(assert= ((repeated/iter square 2) 5)
((repeated/compose square 2) 5))
(let ((v1-raise-power-to-2^n (lambda (n)
((repeated/iter square n) 2)))
(v2-raise-power-to-2^n (lambda (n)
((repeated square n) 2)))
(v3-raise-power-to-2^n (lambda (n)
((repeated/compose square n) 2))) )
(assert= (v1-raise-power-to-2^n 4) (* 1024 64))
(assert= (v2-raise-power-to-2^n 4) (* 1024 64))
(assert= (v3-raise-power-to-2^n 4) (* 1024 64)) )
(let ((v1+n (lambda (n)
(repeated (lambda (x) (+ x 1)) n)))
(v2+n (lambda (n)
(repeated/iter (lambda (x) (+ x 1)) n)))
(v3+n (lambda (n)
(repeated/compose (lambda (x) (+ x 1)) n))))
(assert= ((v1+n 20) 1) 21)
(assert= ((v2+n 20) 1) 21)
(assert= ((v3+n 20) 1) 21))