 
    (nil? y) 1
 
-   (identical? (type x) (type y))
-   (if (implements? IComparable x)
-     (-compare ^not-native x y)
-     (garray/defaultCompare x y))
+   (number? x) (if (number? y)
+                 (garray/defaultCompare x y)
+                 (throw (js/Error. (str "Cannot compare " x " to " y))))
+
+   (satisfies? IComparable x)
+   (-compare x y)
 
    :else
-   (throw (js/Error. "compare on non-nil objects of different types"))))
+   (if (and (or (string? x) (array? x) (true? x) (false? x))
+            (identical? (type x) (type y)))
+     (garray/defaultCompare x y)
+     (throw (js/Error. (str "Cannot compare " x " to " y))))))
 
 (defn ^:private compare-indexed
   "Compare indexed collection."


  IComparable
  (-compare [this other]
    (garray/defaultCompare (.valueOf this) (.valueOf other))))

(extend-type number
  IEquiv

;; IComparable
(extend-protocol IComparable
  Symbol
  (-compare [x y]
    (if (symbol? y)
      (compare-symbols x y)
      (throw (js/Error. (str "Cannot compare " x " to " y)))))

  Keyword
  (-compare [x y]
    (if (keyword? y)
      (compare-keywords x y)
      (throw (js/Error. (str "Cannot compare " x " to " y)))))

  Subvec
  (-compare [x y]
    (if (vector? y)
      (compare-indexed x y)
      (throw (js/Error. (str "Cannot compare " x " to " y)))))
  
  PersistentVector
  (-compare [x y]
    (if (vector? y)
      (compare-indexed x y)
      (throw (js/Error. (str "Cannot compare " x " to " y))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Reference Types ;;;;;;;;;;;;;;;;

