## Clojure’s collections (11/09/2020)

Languages > Clojure

## Generalities

Collections are immutable compound values. There are 4 types of them: Vectors, lists, sets and maps.

``````[1 2 3]  ;Vector
'(1 2 3)  ;List
#{1 2 3}  ;Set
{:a 1, :b 2}  ;Map``````

### Count

All Clojure’s collections can be counted:

``````(count [1 2 3])  ;Will return 3.
(count '(1 2 3))  ;Will return 3.
(count #{1 3 4})  ;Will return 3.
(count {:a 1, :b 2}  ;Will return 2.``````

### Into

The ‘into’ function return a new collection of the type of its first argument containing the elements of its both arguments.

``(into [1 2 3] '(4 5 6))  ;Will return [1 2 3 4 5 6].``

## Vectors

Vectors are sequential and indexed from 0. New elements are always added at the tail.

``````[1 2 3]  ;A vector.
(vector 1 2 3)  ;The 'vector' function construct a vector with its arguments.
(def v [1 2 3])  ;A vector can be bind to a symbol.
(get v 0)  ;The 'get' function return the value at the given index.
(get v 10)  ;Trying to access an non existing index will return 'nil'.
(conj v 4 5 6)  ;The 'conj' function will return a new vector [1 2 3 4 5 6].``````

## Lists

Lists are sequential and non indexed. New elements are always added at the head.

``````'(1 3 3)  ;A list must be prefixed by ' to avoid evaluation as a function call.
(def l '(1 2 3))  ;A list can be bind to a symbol.
(first l)  ;The 'first' function return the first element of the list.
(rest l)  ;The 'rest' function return the list without its first element.
(conj l 4 5 6)  ;The 'conj' function will return a new list (6 5 4 1 2 3).``````

## Sets

Sets are unordered and with no duplicates.

``````#{1 2 3}  ;A set.
(def s #{1 2 3})  ;A set can be bind to a symbol.
(def s2 (conj s 4 5 6))  ;The 'conj' function will return a new set containing 1, 2, 3, 4, 5 and 6.
(disj s2 1 3 5)  ;The 'disj' function will return a new set containing 2, 4 and 6.
(contains? s 3)  ;The 'contains?' function return true if the given element exist in the set, false otherwise.
(conj (sorted-set) 3 1 2)  ;``````

### Sorted sets

``````(def s (sorted-set 1 2 3))  ;The 'sorted-set' function will create the sorted set #{1 2 3}.
(conj s 4 5 6) ;All the sets created from s will be sorted. Here #{1 2 3 4 5 6}.``````

## Maps

Maps share the sets properties but store key/value pairs.
There is a guarantee that functions acting in “sequence” will always walk a particular map instance in the same order.

``````{:a 1 :b 2}  ;A map.
(def m {:a 1 :b 2})  ;A map can be bind to a symbol.
(assoc m :c 3)  ;The 'assoc' function return a new map {:a 1 :b 2 :c 3}.
(assoc m :c 4)  ;If the key already exist the value is changed in the new map {:a 1 :b 2 :c 4}.
(dissoc m :b)  ;The 'dissoc' function return a new map {:a 1}.
(get m :b)  ;The 'get' function return the value associated with the given key. Here 2.
(m :b)  ;Using the map as a function is equivalent to using 'get', but will crash if the map is nil.
(get m :c 0)  ;The 'get' function can get a default, this value will be returned if the key does not exist.
(m :c 0)  ;Same thing using the map directly.
(contains? m :b)  ;The 'contains?' function return true if the given key exist in the set, false otherwise.
(find m :b) ;The 'find' function return a vector containing the key and its value. Here [:b 2].
(keys m)  ;The 'keys' function return a list of all the map's keys. Here (:a :b).
(vals m)  ;The 'vals' function return a list of all the map's values. Here (1 2).
(zipmap [:a :b] [1 2])  ;The 'zipmap' function return a new map {:a 1 :b 2}.
(merge m {:c 3 :d 4})  ;The 'merge' function return a new map {:a 1 :b 2 :c 3 :d 4}.
(merge m {:b 1})  ;In case of conflict the rightmost value win. Here {:a 1 :b 1}.
(merge-with + m {:b 1})  ;The 'merge-with' function use the given function in case of conflict. Here {:a 1 :b 3}.``````

### Sorted maps

Maps are sorted by keys.

``````(def m (sorted-map :b 1 :a 2))  ;The 'sorted-map' function will create the sorted map {:a 2 :b 1}.
(assoc m :c 3) ;All the maps created from m will be sorted. Here {:a 2 :b 1 :c 3}.``````

### Using maps as “C structs”

``````(def Master
{:firstName "Blaise"
:lastName "Ebuth"
:age 666
:occupation "World domination"
{:street "1 Highway to Hell"
:city "Hell-City"
:state "Hell"}})  ;Collections can be nested.
(:age Master "Unknown")  ;Keys can also be used as functions and take a default return value.
(assoc-in Master [:address :street] "2 Highway to Hell")  ;Return a new map with the updated value.
``````(defrecord Person [firstName lastName age])  ;Define a new record structure with the listed fields.