SICP Exercise 2.57
Question
Extend the differentiation program to handle sums and products of arbitrary numbers of (two or more) terms. Then the last example above could be expressed as
(deriv '(* x y (+ x 3)) 'x)
Try to do this by changing only the representation for sums and products,
without changing the deriv
procedure at all. For example, the addend
of a
sum would be the first term, and the augend
would be the sum of the rest of
the terms.
Answer
You only need to touch the augend
and multiplicand
implementations to
accomplish this.
To make this possible, we are going to first check whether the sub-expression
has two elements two be multiplied / summed or more. We can accomplish this by
checking if the third element of the expression is the final one (the first is
the operator, second and third are the two operands). This is the case if
cdddr
is null
. If it is, we simply return caddr
for the multiplicand /
augend the same way we did before.
If the list, however, has more than three total elements (that is, cdddr
is
not null
), we build and return a new list by cons
ing the desired operator
('+
or '*
) with the list elements. This is maybe less elegant than using
make-product
and make-sum
, but easier, since the list has the right level of
nesting right away.
So, here is the implementation of the two functions:
(define (multiplicand p)
(if (null? (cdddr p))
(caddr p)
(cons '* (cddr p))))
(define (multiplier p) (cadr p))
(define (augend s)
(if (null? (cdddr s))
(caddr s)
(cons '+ (cddr s))))
(define (addend s) (cadr s))
Let’s test a simple scenario:
(deriv '(* 1 2 3 4 5 x) 'x)
The result is correct:
120