       :else (if-let [new-formula (try-rule (first rules-left) formula)]
               new-formula
               (recur (rest rules-left) formula)))))
-(defn try-rule [rule expression]
-  (if (= current-goal (rule-goal rule))
-    (try-rule1 rule expression)))
-(defn try-rule1 [rule expression]
-  (cond
-    (atom? expression) nil
-    (match-state (rule-pattern rule) expression) (fire rule)
-    :else (try-rule-on-list rule expression)))
-(defn try-rule-on-list [rule expressions]
-  (if (empty? expression-list)
-    nil
-    (if-let [temp (try-rule1 rule (first expression-list))]
-      (cons temp (rest expression-list))
-      (when-let [temp (try-rule-on-list rule (rest expression-list))]
-        (cons (first expression-list) temp)))))
-(defn fire [rule]
-  (printfn (rule-name rule) " fires.")
-  ((rule-action rule)))
+(defn control []
+  ; TODO: current-formula is unbound
+  (loop [current-formula '()]
+      (if-let [new-formula (try-rules rules current-formula)]
+        (recur new-formula)
+        current-formula)))

(ns chapter3.leibniz
  (:refer chapter3.match :only [match atom?]))
(defn nested-diff-sum? [d v]
  (when-let [d2 (and (not (atom? v)) (match '(+ (? e1) (? e2)) v))]
    (merge d d2)))
(defn nested-diff-x1? [d v]
  (assoc d :e1 v))
(defn nested-diff-x2? [d v]
  (= v (d :e1)))
(def diff-sum-rule

   "diff-x-rule"])
; other rules go here ...

; TODO: Clojure HAS to have a class/record facility to do this...
(def rule-goal first)
(def rule-pattern second)
(defn rule-action [rule] (nth rule 2))
(defn rule-name [rule] (nth rule 3))
(def rules
  [diff-sum-rule diff-x-rule])
;;; control scheme ;;;
; (I don't know--that's just what the book calls it)
(declare try-rule1)
(defn try-rule-on-list [rule expressions]
  (if (empty? expressions)
    nil
    (if-let [temp (try-rule1 rule (first expressions))]
      (cons temp (rest expressions))
      (when-let [temp (try-rule-on-list rule (rest expressions))]
        (cons (first expressions) temp)))))
(defn fire [rule]
  (println (rule-name rule) " fires.")
  ((rule-action rule)))
(defn try-rule1 [rule expression]
  (cond
    (atom? expression) nil
    (match-state (rule-pattern rule) expression) (fire rule)
    :else (try-rule-on-list rule expression)))
(defn try-rule [rule expression]
  (if (= current-goal (rule-goal rule))
    (try-rule1 rule expression)))
(defn try-rules [rules formula]
  (loop [rules-left rules]
    (cond
