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) 625Hint: You may find it convenient to use
compose
from exercise 1.42.First of all, let's just clarify what we're asked for here. We're not being asked to define a procedure that can take, for example,
(lambda (x) (+ x 1))
and the value n
and return the procedure (lambda (x) (+ x n))
. Instead we're being asked to define a procedure that returns a procedure that computes the nth repeated application of f. I.e. it applies f n times in sequence.We're also given a nice hint. We can use
compose
to do this. And we can do this with an iterative procedure. How? Well, compose
allows us to combine two single-parameter procedures together to produce a procedure that is the result of applying the first to the result of the second. All we need to do is to start with f as our result, and iterate from 1..n, at each step composing the result so far with another application of f, until we reach n, at which point we'll have our desired procedure:
(define (repeated f n) (define (iter i result) (if (= i n) result (iter (+ i 1) (compose f result)))) (iter 1 f))Of course we can be a bit smarter about this... Back in section 1.2.4 we learned about the successive squaring approach to exponentiation. We can use a similar approach for producing the procedure that calculates the nth repeated application of f by noting that:
- When n is even,
(repeated f n)
≡(compose ff ff)
, whereff
is defined as(repeated f (/ n 2))
. - When n is odd,
(repeated f n)
≡(compose f (repeated f (- n 1)))
repeated
and the procedure produced will likely have a more compact representation. Here's the smarter version:
(define (repeated f n) (cond ((= n 1) f) ((even? n) (let ((ff (repeated f (/ n 2)))) (compose ff ff))) (else (compose f (repeated f (- n 1))))))And to confirm this works:
> ((repeated square 2) 5) 625 > (define add10 (repeated inc 10)) > (add10 5) 15 > (add10 20) 30 > (add10 (add10 3)) 23
No comments:
Post a Comment