Clojure collection quirks - Vectors
Working with Clojure collections is a pleasure. Yet, sometimes one may run into unexpected behaviors. In this series, we take a look at the most simple Clojure data structures.
Vectors
Vectors are sequential collections with constant time random access capability. One can also view vectors as integer to element mappings. Examples:
Access
You can acces an element on the nth index with the get
function or the nth
function. Be aware that when a given index is not found the get
function returns nil
while the nth
function throws an IndexOutOfBoundsException
. You can specify a default value as a third argument that is returned when the index is not found.
Vectors also act like functions (they implement the clojure.lang.IFn
interface). An IOOBE exception is thrown when called on an uknown index.
Modify
We can also modify an item on an index of a vector:
That’s right, one can change an item on an index of a vector just like with a map.
How is about removing an item from a vector?
You can not call dissoc
on a vector because that could not remove an item without affecting the indices of all other items after the given index. To remove an item, first you need to split the vector into two parts (calling subvec
) and then create a vector from the concatenation of the result.
You can use the subvec
function to return part of a vector.
Usage as queues
Vectors are often used as queues.
- The
conj
function appends a value to the end of the vector. - The
peek
function returs the last item of the vector in constant time. (Thelast
function is linear time thus much slower usually.) - The
pop
function drops the last item from a vector.
Sequences
You can turn a vector to a sequence with the seq
function (note that (seq [])
is nil
). The rseq
function returns a lazy sequence of items in the vector in reverse order. It is advised to favor rseq
over reverse
because of the constant time complexity and lazyness.