Exercise 1.41 asks us to define a procedure
doublethat takes a procedure of one argument as its argument and returns a procedure that applies the original procedure twice. For example, if
incis a procedure that adds 1 to its argument, then
(double inc)should return a procedure that adds 2. We need to be able to use our
doubleprocedure to evaluate expressions like
(((double (double double)) inc) 5)
Just like the previous exercise, we can use
lambdato return a procedure from a procedure.
(define (double f)
(lambda (x) (f (f x))))
We'll also need to define a couple of procedures to test with.
(define (inc x) (+ x 1))
(define (square x) (* x x))
> ((double inc) 1)
> ((double square) 2)
As you can see, the name
doubleis a little bit misleading. The procedure doesn't apply the input procedure then double the result, it applies the input procedure the applies it again to the result.
So in the first test the input parameter 1 is incremented, then the resulting value is incremented again. Likewise in the second test, the input parameter 2 is squared, then the result is squared.
Here's the result from running the test case given in the text:
Here we have nested calls to
> (((double (double double)) inc) 5)
doubleitself. One set of nested calls to
doublehas the effect of quadrupling the input procedure. Nesting it again results in 16 calls to
Exercise 1.42 asks us to define a procedure
composethat implements the composition of two functions that are supplied as input parameters. This is very similar to the
doubleprocedure we saw in the last exercise, but instead of applying the same procedure twice, we're given two different procedures.
If we evaluate
((compose square inc) 6)
we should get back a value of 49 because the input 6 will first be incremented then squared.
(define (compose f g)
(lambda (x) (f (g x))))
We can run two tests to show the order that the input procedures are evaluated.
> ((compose square inc) 6)
> ((compose inc square) 6)
Exercise 1.43 asks us to write a procedure that takes a procedure and a number n as arguments, and returns a procedure that applies the input procedure n times. We can make use of the
composeprocedure from the previous exercise.
(define (repeated f x)
(if (= x 1)
(compose f (repeated f (- x 1)))))
Repeatedly incrementing a value n times should give us the expected result of just adding n to the original value.
> ((repeated inc 2) 5)
> ((repeated inc 10) 10)
Squaring a value twice has the effect of raising it to the 4th power.
> ((repeated square 2) 5)
For links to all of the SICP lecture notes and exercises that I've done so far, see The SICP Challenge.