Lists and Vectors
Prerequisites: Functions
Clojure has two main ordered collections.
Vectors
A vector [...] is the everyday ordered collection — fast access by
index and fast adding at the end.
(def v [10 20 30])
(println (first v) (second v) (last v))
(println (nth v 1) (get v 1) (v 1)) ; three ways to index
(println (get v 99) (get v 99 :none))
(println (count v))
(println (conj v 40)) ; adds at the end
(println (assoc v 0 11)) ; "replace" index 0
(println (pop v) (peek v))
(println (subvec [1 2 3 4 5] 1 3))
(println (into [0] [1 2 3]))
10 20 30
20 20 20
nil :none
3
[10 20 30 40]
[11 20 30]
[10 20] 30
[2 3]
[0 1 2 3]
Every operation returns a new vector; v is still [10 20 30].
nth throws for an out-of-range index, while get returns nil (or a
default). A vector is also a function of its indexes: (v 1).
Lists
A list '(...) is a linked list — fast at the front, slow for
indexing. You use lists mostly as code; as data, vectors are
usually a better choice.
(def l '(10 20 30))
(println (first l) (rest l))
(println (conj l 5)) ; adds at the FRONT
(println (cons 1 l))
(println (list 1 2 (+ 1 2))) ; list evaluates its arguments
(println '(1 2 (+ 1 2))) ; quote doesn't
10 (20 30)
(5 10 20 30)
(1 10 20 30)
(1 2 3)
(1 2 (+ 1 2))
conj adds where it's cheapest: the end of a vector, the front of a
list.
Sequence functions work on both
(def nums [5 3 8 1 9 2])
(println (sort nums) (reverse nums))
(println (take 3 nums) (drop 3 nums))
(println (apply max nums) (reduce + nums))
(println (contains? [:a :b] 1)) ; checks INDEX 1, not the value
(println (some #{8} nums)) ; the idiomatic "does it contain 8?"
(println (vec (range 5)))
(println (distinct [1 1 2 3 3]))
(println (concat [1 2] [3] '(4 5)))
(1 2 3 5 8 9) (2 9 1 8 3 5)
(5 3 8) (1 9 2)
9 28
true
8
[0 1 2 3 4]
(1 2 3)
(1 2 3 4 5)
Functions like sort, take, and reverse return sequences, which
print with parentheses. Wrap them in vec or into [] when you need a
vector back.
Common mistakes
(contains? coll x)checks for a key — an index for vectors. To test membership of a value, use a set orsome.
Practice
Start with [5 3 8 1], add 7, remove the smallest number, and print
the result sorted from largest to smallest.
Show solution
(def nums (conj [5 3 8 1] 7))
(def smallest (apply min nums))
(println (sort > (remove #(= % smallest) nums)))
(8 7 5 3)