Collections
Clojure has support for lists, maps, sets and vectors. Clojure collections are immutable. Instead of mutating the collection, Clojure function takes arguments and returns a new collection without affecting the original. Any of these collections can be represented with Seq abstraction
Persistent Data Structures
- New values are built from old values + modifications
- New values are not full copies
- New values and old value are both available after changes
- All Clojure collections are persistent
Sequential and Associative data structures
- Sequential - List, Vector
- Associative - Map, Vector Both support declarative destructuring
List
() ;=> empty list
(1 2 3) ;= error because 1 is not a function
(list 1 2 3) ;=> (1 2 3)
'(1 2 3) ;=> (1 2 3)
(conj '(2 3) 1) ;=> (1 2 3) conj adds element to collection in most efficient way. For list its adds at front
Vector
[] ;=> empty vector
[1 2 3] ;= [1 2 3]
(vector 1 2 3) ;=> [1 2 3]
(vec '(1 2 3)) ;=> [1 2 3] vec converts list to vector
(nth [1 2 3] 1] ;=> 2
(conj '[2 3] 1) ;=> [2 3 1] For vector conj adds at the end
Map
{} ;=> empty map
{ :a 1 :b 2} ;=> { :a 1 :b 2}
(:a { :a 1 :b 2}) ;=> 1
({ :a 1 :b 2} :a) ;=> 1
(assoc { :a 1} :b 2) ;=> { :a 1 :b 2}
(dissoc { :a 1} :a) ;=> {}
(conj {} [:a 1]) ;=> {:a 1}
(def jdoe {:name "John Doe" :address {:zip 33455}})
(get-in jdoe [:address :zip])
(assoc-in jdoe [:address :zip] 27514)
(update-in jdoe [:address :zip] inc)
Set
#{} ;=> empty set
#{:a :b} ;=> #{:a :b}
(#:{:a :b} :a) ;=> :a
(conj #{} :a) ;=> #{: a}
(contains? #{:a} :a) ;=> true
Concise Collection Access
Since Clojure collections are functions there are many concise ways to work on collections
(get [:a :b :c] 2)
is equivalent to ([:a :b :c] 2)
(get {:a 5 :b 6} :c 7)
is equivalent to ([({:a 5 :b 6} :c 7)
Collection keys are (often) functions
(get {:a 5 :b 6} :b)
is equivalent to (:b {:a 5 :b 6})
(get {:a 5 :b 6} :c 7)
is equivalent to (:c {:a 5 :b 6} 7)