Learning Clojure/Data Structures
Sets
editA set is a collection containing no duplicate items. Clojure has two set types:
- a hash set is implemented as a hashmap and so has (near) constant lookup, insertion, and removal times.
- a sorted set is implemented as an ordered binary tree and so has logarithmic lookup, insertion, and removal times.
The reader recognizes a literal syntax for hash sets:
#{67 2 8.8 -78} ; a hash set of four numbers
Lazy sequences
editMany sequence functions produce lazy sequences, which are sequences not actually backed by their own data: the items of a lazy sequence are produced on request from a function or retrieved from some other source, such as another collection. For example, the sequence representing the first 8 items of a pre-existing vector can be lazy because there's no need to copy the items: if we, say, request the 3rd item of the lazy sequence, we get back the 3rd item of the vector.
A lazy sequence based on a function produces items based on the index passed to the function. Because such sequences are backed by no actual data at all, they can be infinite in size. For instance, the function cycle returns a lazy sequence representing the endless repetition of another sequence:
(cycle [1 2 3]) ; returns a lazy sequence of 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3... etc.
[hmm, under what scenarios does a lazy seq keep around the items as they're produced? I assume a cycle doesn't end up backed by a huge actual list or vector, but doseq does seem to keep around the produced values. What other cases are like doseq?]
StructMaps
editWhat Clojure calls a structmap (as in "structure-map") is simply a variant of a persistent hashmap, but one in which a pre-defined set of keys have optimized storage and lookup.
A structmap is created by first calling clojure/create-struct to define a blueprint called a basis. The function clojure/struct-map is then used to create actual structmaps using a basis:
(def george (create-struct :apple :banana :orange))
(struct-map george :apple 3 :banana 9 :orange 12) ; create a structmap with the key-val pairs :apple => 3, :banana => 9, and :orange => 12
(struct-map george :banana 9 :apple 3 :orange 12) ; notice the key order need not be that used in create-struct
(struct-map george :apple 3 :orange 12) ; the key :banana is not specified, so its value defaults to nil
You can create a structmap by specifying only the values for the keys using clojure/struct:
(struct george -87 0 9) ; keys implied by their order in create-struct, so this is :apple => -87, :banana => 0, :orange => 12