We said that we would support the following kinds of expressions:
; expression: ; number ; variable ; sum: (+ expression expression) ; product: (* expression expression)Obviously the code will involve several different cases to handle, so it makes sense to use a cond:
(define (derivative exp var) (cond ...We first included a case for constants, where the derivative is 0:
(define (derivative exp var) (cond ((number? exp) 0) ...Then we included a case for a single variable. In that case, the derivative is 1 if the variable is the same variable we are using to take the derivative and otherwise the answer is 0:
(define (derivative exp var) (cond ((number? exp) 0) ((symbol? exp) (if (eq? exp var) 1 0)) ...I mentioned that an eq? comparison works because any given symbol will have a unique address in Scheme. Then we turned to the more interesting case of handling a sum. I pointed out that it is useful to introduce helper functions to make the code more readable and to allow us to break up the coding task into smaller tasks. It will turn out that we can also redefine the helper functions to make the code work better.
We decided to have helper functions for testing whether it's a sum, for making a sum, and for finding the first and second arguments of the expression. Putting these together, we were able to add this extra clause to our cond:
((sum? exp) (make-sum (derivative (arg1 exp) var) (derivative (arg2 exp) var)))Then we wrote the helper functions. The arg1 and arg2 functions were fairly simple:
(define (arg1 exp) (cadr exp)) (define (arg2 exp) (caddr exp))The sum? function was a little trickier. In general we want to see if the list begins with the symbol +, but we had to be careful in case what we are given is either not a list or is empty. There is a great predicate for this in Scheme called pair?. If something is a pair, then it has both a car and a cdr. So we wrote sum? as follows:
(define (sum? exp) (and (pair? exp) (eq? (car exp) '+)))Someone pointed out that it is important to know that the function and does short-circuited evaluation. The final helper function was to form a sum:
(define (make-sum exp1 exp2) (list '+ exp1 exp2))We also introduced a case for calling the error procedure if none of our cases match. We ran our code to test it and then went back and added similar code for handling products. Below is the final version of the code that we produced:
(define (derivative exp var) (cond ((number? exp) 0) ((symbol? exp) (if (eq? exp var) 1 0)) ((sum? exp) (make-sum (derivative (arg1 exp) var) (derivative (arg2 exp) var))) ((product? exp) (make-sum (make-product (arg1 exp) (derivative (arg2 exp) var)) (make-product (derivative (arg1 exp) var) (arg2 exp)))) (else (error "illegal expression")))) (define (arg1 e) (cadr e)) (define (arg2 e) (caddr e)) (define (make-sum a1 a2) (list '+ a1 a2)) (define (make-product m1 m2) (list '* m1 m2)) (define (sum? x) (and (pair? x) (eq? (car x) '+))) (define (product? x) (and (pair? x) (eq? (car x) '*)))I said that we'd explore this further in section.