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