 
 ;; public interface
 
-(deftype BTSet [root shift comparator]
+(deftype BTSet [root shift cnt comparator meta ^:mutable __hash]
   Object
-;;   (toString [this]
-;;     (pr-str* this))
-  
+  (toString [this]
+    (pr-str* this))
+  
+  ICloneable
+  (-clone [_] (BTSet. root shift cnt comparator meta __hash))
+
+  IWithMeta
+  (-with-meta [_ new-meta] (BTSet. root shift cnt comparator new-meta __hash))
+
+  IMeta
+  (-meta [_] meta)
+ 
+  IEmptyableCollection
+  (-empty [_] (BTSet. (LeafNode. (array)) 0 0 comparator meta 0))
+  
+  IEquiv
+  (-equiv [this other]
+    (and
+     (set? other)
+     (== cnt (count other))
+     (every? #(contains? this %) other)))
+
+  IHash
+  (-hash [coll] (caching-hash coll hash-iset __hash))
+   
   ICollection
   (-conj [set key] (btset-conj set key))
 

    (reduce -conj (btset) keys)))

;; helpers


(defn parse-path [path shift]
  (loop [level shift

          xs-sorted (distinct (sort xs))
          set0      (into (btset) xs)
          rm        (repeatedly (rand-int 10000) #(rand-nth xs))
          xs-rm     (reduce disj (into (sorted-set) xs) rm)
          set1      (reduce disj set0 rm)]          
      (when-not (= (vec set0) xs-sorted)
        (throw (js/Error. (str "conj failed on: " xs))))
      (when-not (= set0 (set xs-sorted))
        (throw (js/Error. (str "equiv 1 failed on: " xs))))
      (when-not (= (count set0) (count xs-sorted))
        (throw (js/Error. (str "count 1 failed on: " xs))))
      (when-not (= (vec set1) (vec xs-rm))
        (throw (js/Error. (str "disj failed on: " xs " and " rm))))
      (when-not (= (count set1) (count xs-rm))
        (throw (js/Error. (str "count 2 failed on: " xs " and " rm))))
      (when-not (= set1 xs-rm)
        (throw (js/Error. (str "equiv 2 failed on: " xs))))
      (println "Checking...")))
  (println "Checked")
  :ok)
