       (when-let [temp (try-rule-on-list rule (rest expressions))]
         (cons (first expressions) temp)))))
 (defn fire [rule d]
-  ;(println (rule-name rule) "fires.")
-  ((rule-action rule) d))
+  ;(println (:name rule) "fires.")
+  ((:action rule) d))
 (defn try-rule [rule expression]
   (if (atom? expression)
     nil
-    (if-let [d (match-state (rule-pattern rule) expression)]
+    (if-let [d (match-state (:pattern rule) expression)]
       (fire rule d)
       (try-rule-on-list rule expression))))
 (with-test

       (when-let [d2 (match-state '(exp (? e1) (number-state? e2)) x)]
         (merge d d2))))
(def diff-power-rule
  ['(d (diff-power-e3-rule e3) (? v1))
   (fn [d] (list '* (d 'e2)
                 (list '* (list 'exp (d 'e1) (list 'dec (d 'e2)))
                       (list 'd (d 'e1) (d 'v1)))))
   "diff-power-rule"])
(def ladd-zero-rule ['(+ (? x) 0) #(% 'x) "ladd-zero-rule"])
(def radd-zero-rule ['(+ 0 (? x)) #(% 'x) "radd-zero-rule"])
(def add-const-rule ['(+ (number-state? x) (number-state? y)) #(+ (% 'x) (% 'y)) "add-const-rule"])
(def lprod-zero-rule ['(* (? x) 0) (fn [d] 0) "lprod-zero-rule"])
(def rprod-zero-rule ['(* 0 (? x)) (fn [d] 0) "rprod-zero-rule"])
(def lprod-id-rule ['(* (? x) 1) #(% 'x) "lprod-id-rule"])
(def rprod-id-rule ['(* 1 (? x)) #(% 'x) "rprod-id-rule"])
(def prod-const-rule ['(* (number-state? x) (number-state? y)) #(* (% 'x) (% 'y)) "prod-const-rule"])
(def exp-zero-rule ['(exp (? x) 0) (fn [d] 1) "exp-zero-rule"])
(def exp-id-rule ['(exp (? x) 1) #(% 'x) "exp-id-rule"])
(def dec-rule ['(dec (number-state? x)) #(dec (% 'x)) "dec-rule"])
; other rules go here ...

; TODO: Clojure HAS to have a class/record facility to do this...
(def rule-pattern first)
(def rule-action second)
(defn rule-name [rule] (nth rule 2))

(def rules
  [[diff-sum-rule diff-x-rule diff-const-rule diff-product-rule diff-power-rule]

(ns chapter3.leibniz
  (:refer chapter3.match :only [match match-state atom?])
  (:refer clojure.test :only [with-test is run-tests]))

(defrecord rule [pattern action name])
(defn nested-diff-sum? [d v]
  (and (not (atom? v)) 
       (when-let [d2 (match-state '(+ (? e1) (? e2)) v)]
         (merge d d2))))
(def diff-sum-rule
  (->rule '(d (nested-diff-sum? e3) (? v1))
   #(list '+ (list 'd (% 'e1) (% 'v1)) (list 'd (% 'e2) (% 'v1)))
   "diff-sum-rule"))
(defn nested-diff-x1? [d v] d)
(defn nested-diff-x2? [d v] (and (= v (d 'e1)) d))
(def diff-x-rule
  (->rule '(d (nested-diff-x1? e1) (nested-diff-x2? e2))
   (fn [d] 1)
   "diff-x-rule"))
(with-test
  (defn exists-tree? [f v1]
    (if (atom? f)
