 (defn match-error-map [arity alts]
   {:arity arity
    :alternatives (sort-by :generality (clean-alts alts))})
-
-(defn resolve-fn-call [system dispatch-state args]
-  (let [arity (count args)
-        alternatives (map (fn [[k alt]]
-                            (merge alt ((:match-fn alt)
-                                        system
-                                        (:feature-extractor dispatch-state)
-                                        args)))
-                          (get-in dispatch-state [:dispatch-map arity]))
-        matching-alternatives (sort-by :generality (filter :satisfied? alternatives))]
-
-    (println "The alternatives are ")
-    (clojure.pprint/pprint matching-alternatives)
-    
-    (cond
-      (empty? matching-alternatives) (throw (ex-info "No matching set-fn for this arity."
-                                                     (match-error-map
-                                                      arity
-                                                      alternatives)))
-      (= (:generality (first matching-alternatives))
-         (:generality (second matching-alternatives))) (throw
-                                                        (ex-info
-                                                         "Ambiguous set-based dispatch"
-                                                         (match-error-map
-                                                          arity
-                                                          matching-alternatives)))
-      :default (apply (-> matching-alternatives
-                          first
-                          :fn)
-                      args))))
-
-(defn dispatch-root [system dispatch-state]
-  (fn [& args]
-    (let [system (mark-called system)]
-      (if (empty? args)
-        dispatch-state
-        (resolve-fn-call system
-                         (deref dispatch-state)
-                         args)))))
-
-(defn initialize-dispatch-state [feature-extractor]
-  {:dispatch-map {}
-   :feature-extractor feature-extractor})
-
-(defn forward-set-fn [f]
-  (fn [& args]
-    (let [[system & rest-args] args]
-      (swap! system (fn [set-registry]
-                      (check-not-used set-registry)
-                      (apply f `(~set-registry ~@rest-args)))))))
-
-(defn add-method [state-atom arity method]
-  (swap! state-atom
-         (fn [state]
-           (update-in state [:dispatch-map arity]
-                      #(conj (or % {}) [(:args method) method])))))
-
-(def memoized-evaluate-query (memoize ss/evaluate-query))
-
-(defn evaluate-arg-match [system common-feature-extractor arg-spec arg]
-  (let [fe (or (:feature-extractor arg-spec)
-               common-feature-extractor)
-        element (fe arg)
-
-        _ (utils/data-assert (ss/element? system element)
-                             "Not an element"
-                             {:x element
-                              :elements (ss/all-elements system)})
-        
-        raw-query (:query arg-spec)
-        query (ss/normalize-query raw-query)
-
-        ;; TODO: This can be cached
-        elements (memoized-evaluate-query system query)
-
-        ;; NOTE: A a query can be satisfied even if the elements returned by
-        ;; evaluate-query is empty.
-        satisfied? (ss/satisfies-query? system query element)
-        
-        generality (count elements)]
-    (utils/map-of element satisfied? generality raw-query elements)))
 
 (defn compare-sets
   "Encode the relationship between two sets:

            [clojure.spec.alpha :as spec]
            [bluebell.utils.core :as utils]
            [bluebell.utils.specutils :as sutils]
            [clojure.set :as cljset])
  (:refer-clojure :exclude [complement any?]))



    (and (not (some nil? comparisons))
         (every? #(<= % 0) comparisons)
         (some (partial = -1) comparisons))))

(defn alt-set-vector [alt]
  (mapv :elements (:args alt)))

(def memoized-set-vectors-dominate? (memoize set-vectors-dominate?))

(defn alt-dominates? [a b]
  (memoized-set-vectors-dominate? (alt-set-vector a)
                                  (alt-set-vector b)))

(defn resolve-fn-call [system dispatch-state args]
  (let [arity (count args)
        alternatives (map (fn [[k alt]]
                            (merge alt ((:match-fn alt)
                                        system
                                        (:feature-extractor dispatch-state)
                                        args)))
                          (get-in dispatch-state [:dispatch-map arity]))
        matching-alternatives (filter :satisfied? alternatives)
        frontier (pareto/elements (reduce pareto/insert
                                          (pareto/frontier alt-dominates?)
                                          matching-alternatives))]
    (cond
      (empty? frontier) (throw (ex-info "No matching set-fn for this arity."
                                        (match-error-map
                                         arity
                                         alternatives)))
      (< 1 (count frontier)) (throw
                                                        (ex-info
                                                         "Ambiguous set-based dispatch"
                                                         (match-error-map
                                                          arity
                                                          matching-alternatives)))
      :default (apply (-> frontier
                          first
                          :fn)
                      args))))

(defn dispatch-root [system dispatch-state]
  (fn [& args]
    (let [system (mark-called system)]
      (if (empty? args)
        dispatch-state
        (resolve-fn-call system
                         (deref dispatch-state)
                         args)))))

(defn initialize-dispatch-state [feature-extractor]
  {:dispatch-map {}
   :feature-extractor feature-extractor})

(defn forward-set-fn [f]
  (fn [& args]
    (let [[system & rest-args] args]
      (swap! system (fn [set-registry]
                      (check-not-used set-registry)
                      (apply f `(~set-registry ~@rest-args)))))))

(defn add-method [state-atom arity method]
  (swap! state-atom
         (fn [state]
           (update-in state [:dispatch-map arity]
                      #(conj (or % {}) [(:args method) method])))))

(def memoized-evaluate-query (memoize ss/evaluate-query))

(defn evaluate-arg-match [system common-feature-extractor arg-spec arg]
  (let [fe (or (:feature-extractor arg-spec)
               common-feature-extractor)
        element (fe arg)

        _ (utils/data-assert (ss/element? system element)
                             "Not an element"
                             {:x element
                              :elements (ss/all-elements system)})
        
        raw-query (:query arg-spec)
        query (ss/normalize-query raw-query)

        ;; TODO: This can be cached
        elements (memoized-evaluate-query system query)

        ;; NOTE: A a query can be satisfied even if the elements returned by
        ;; evaluate-query is empty.
        satisfied? (ss/satisfies-query? system query element)
        
        generality (count elements)]
    (utils/map-of element satisfied? generality raw-query elements)))

(defn make-match-fn [meta arg-specs]
  (fn [system common-feature-extractor args]
