2 (:refer-clojure :exclude (number?))
6 ;;; differentiation of infix expressions
7 ;; part b. Assume standard algebraic form.
20 (defn- first-expr* [expr op]
21 (cond (and (nil? (peek-op expr)) (empty? expr)) nil
22 (and (same-op? op (peek-op expr))
23 (= op '*)) (cons (first expr) (cons (second expr) (first-expr* (rest (rest expr)) op)))
24 :else (list (first expr))))
26 (defn first-expr [expr]
27 (let [op (second expr)]
29 (first-expr* expr op))))
31 (defn- rest-expr* [expr op]
32 (cond (empty? expr) nil
33 (and (same-op? op (peek-op expr)) (= op '*)) (rest-expr* (rest (rest expr)) op)
34 :else (rest (rest expr))))
36 (defn rest-expr [expr]
37 (let [op (second expr)]
39 (rest-expr* expr op))))
41 (defn- op-expr* [expr op]
42 (cond (empty? expr) nil
43 (same-op? op (peek-op expr)) (op-expr* (rest (rest expr)) op)
44 :else (if (= op '*) (peek-op expr) op)))
47 (let [op (second expr)]
51 (defn exponentiation? [exp]
66 (defn same-variable? [v1 v2]
67 (cond (list? v1) (and (variable? v1)
70 (list? v2) (and (variable? v1)
73 :else (and (variable? v1)
80 (clojure.core/number? (first exp))
81 (clojure.core/number? exp)))
83 (defn =number? [exp num]
87 (defn make-sum [a1 a2]
88 (cond (=number? a1 0) a2
90 (and (number? a1) (number? a2)) (+ a1 a2)
91 :else (list a1 '+ a2)))
93 (defn make-product [m1 m2]
94 (cond (or (=number? m1 0) (=number? m2 0)) 0
97 (and (number? m1) (number? m2)) (* m1 m2)
98 :else (list m1 '* m2)))
101 (and (list? x) (= (op-expr x) '+)))
104 (let [a (first-expr s)]
111 (let [a (rest-expr s)]
127 (defn multiplicand [p]
128 (let [m (rest (rest p))]
134 (defn make-exponentiation [b n]
135 (cond (=number? b 1) 1
139 (and (number? b) (number? n)) (Math/pow b n)
140 :else (list b '** n)))
142 (defn deriv [exp var]
143 (cond (number? exp) 0
144 (variable? exp) (if (same-variable? exp var) 1 0)
145 (sum? exp) (make-sum (deriv (addend exp) var)
146 (deriv (augend exp) var))
147 (product? exp) (make-sum (make-product (multiplier exp)
148 (deriv (multiplicand exp) var))
149 (make-product (deriv (multiplier exp) var)
151 (exponentiation? exp) (make-product (exponent exp)
152 (make-product (make-exponentiation (base exp)
153 (- (exponent exp) 1))
154 (deriv (base exp) var)))
155 :else (str "unknown expression type -- deriv " exp)))
158 (deftest test-deriv-and-helpers
171 (first-expr e4) '(x * y)
176 (rest-expr e7) '(2 * x + 2)
177 (first-expr e8) '(x * y)
179 (rest-expr e8) '(1))))