Skip to content
AgileLogics
4 min read

Sets

Prerequisites: Maps

A set #{...} holds unique values with fast membership tests.

(def tags #{:clojure :jvm :lisp})

(println (contains? tags :jvm))
(println (tags :lisp) (tags :python))     ; a set is a function too
(println (conj tags :fp))
(println (disj tags :jvm))
(println (count (conj tags :jvm)))        ; already there: no change
(println (set [1 2 2 3 3 3]))
(println (sorted-set 3 1 2))
true
:lisp nil
#{:lisp :clojure :jvm :fp}
#{:lisp :clojure}
3
#{1 3 2}
#{1 2 3}

Calling a set with a value returns the value if it's present and nil otherwise, so a set works as a predicate:

(def vowel? #{\a \e \i \o \u})

(println (filter vowel? "programming"))
(println (remove #{0} [1 0 2 0 3]))
(o a i)
(1 2 3)

Set operations

(require '[clojure.set :as set])

(def backend #{"ada" "linus" "grace"})
(def frontend #{"grace" "tim"})

(println (sort (set/union backend frontend)))
(println (set/intersection backend frontend))
(println (sort (set/difference backend frontend)))
(println (set/subset? #{"tim"} frontend))
(ada grace linus tim)
#{grace}
(ada linus)
true

Set order isn't defined, so the examples sort results before printing. clojure.set also has relational functions like join, index, and rename-keys for sets of maps.