Skip to content

Instantly share code, notes, and snippets.

@raek
Created March 31, 2010 22:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raek/350986 to your computer and use it in GitHub Desktop.
Save raek/350986 to your computer and use it in GitHub Desktop.
(ns se.raek.bag
(:import [clojure.lang ILookup IPersistentSet]))
(defn- update
([map key f]
(assoc map key (f (get map key))))
([map key not-found f]
(assoc map key (f (get map key not-found)))))
(deftype HashBag [map size]
:as this
ILookup
(valAt [key]
(if (contains? map key)
key
nil))
(valAt [key not-found]
(if (contains? map key)
key
not-found))
IPersistentSet
(count []
size)
(cons [key]
(new HashBag (update map key 0 inc) (inc size)))
(disjoin [key]
(condp = (get map key)
nil (throw (IllegalStateException. "Can't disjoin non-existing key"))
1 (new HashBag (dissoc map key) (dec size))
(new HashBag (update map key dec) (dec size))))
(contains [key]
(contains? map key))
(get [key]
(if (contains? map key)
key
nil))
(empty []
(new HashBag (hash-map) 0))
(equiv [o]
(and (= (class this) (class o))
(= (.map this) (.map o))))
(seq []
(mapcat #(let [[key n] %] (repeat n key))
map)))
(defn hash-bag [& keys]
(into (HashBag (hash-map) 0) keys))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment