Last active
March 13, 2020 11:27
-
-
Save hindol/c92a768f7f784379dc8bcd546a60fa42 to your computer and use it in GitHub Desktop.
Bag / MultiSet in Clojure (How to create a custom collection in Clojure)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns com.github.hindol.euler.collections | |
(:import | |
(clojure.lang IPersistentCollection | |
IPersistentSet | |
Seqable))) | |
(deftype Bag [^clojure.lang.IPersistentMap m | |
^long n] | |
IPersistentSet | |
(get [this k] | |
(if (contains? m k) k nil)) | |
(contains [this k] | |
(contains? m k)) | |
(disjoin [this k] | |
(Bag. (if (= 1 (m k)) (dissoc m k) (update m k dec)) | |
(dec n))) | |
IPersistentCollection | |
(count [this] | |
n) | |
(empty [this] | |
(Bag. (.empty m) 0)) | |
(cons [this k] | |
(Bag. (assoc m k (inc (get m k 0))) | |
(inc n))) | |
(equiv [this o] | |
(and (isa? (class o) Bag) | |
(= n (.n ^Bag o)) | |
(.equiv m (.m ^Bag o)))) | |
Seqable | |
(seq [this] (mapcat repeat (vals m) (keys m)))) | |
(defn bag | |
[& keys] | |
(Bag. (frequencies keys) | |
(count keys))) | |
; (coll/bag 1 2 2 3 3 3) => #{1 2 2 3 3 3} | |
; (conj (coll/bag 1 2 2 3 3 3) 4 4 4 4) => #{1 2 2 3 3 3 4 4 4 4} | |
; (disj (coll/bag 1 2 2 3 3 3) 3) => #{1 2 2 3 3} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Scaffold generated using this utility function: https://gist.github.com/semperos/3835392