Sequences

Clojure defines many algorithms in terms of sequences (seqs). A seq is a logical list, and unlike most Lisps where the list is represented by a concrete, 2-slot structure, Clojure uses the ISeq interface to allow many data structures to provide access to their elements as sequences. The seq function yields an implementation of ISeq appropriate to the collection. Seqs differ from iterators in that they are persistent and immutable, not stateful cursors into a collection. As such, they are useful for much more than foreach - functions can consume and produce seqs, they are thread safe, they can share structure etc.


Most of the sequence library functions are lazy, i.e. functions that return seqs do so incrementally, as they are consumed, and thus consume any seq arguments incrementally as well. Note that generally the first item is always produced, in order to determine if in fact there is a sequence at all, and the rest function is lazy, producing successive values only when called. Functions returning lazy seqs can be implemented using the lazy-cons macro.


When seq is used on native Java arrays and objects that implement Iterable, the resulting sequence is still immutable and persistent, and will represent a single pass across the data. Because that pass might happen lazily, the pass might see changes that happen after seq has been called. Also, if the backing iterator is subject to ConcurrentModificationException, then so too is the resulting seq. That said, there is still a lot of utility to using seq on Iterables and arrays - since seqs support multi-pass and lazy algorithms. Robust programs should not mutate arrays or Iterables that have seqs on them.


In all the functions that follow, if the arguments are specified as collections, seq will be called on the collection and the function operates on the result, i.e. the functions take collections but operate on their seqs.


The Seq interface:


(first coll)

Returns the first item in the collection. Calls seq on its argument. If coll is nil, returns nil.


(rest coll)

Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil.


(cons item seq)

Returns a new seq where item is the first element and seq is the rest.


The Seq library:


(ffirst coll)

(frest coll)

(rfirst coll)

(rrest coll)

(first (first coll)), (first (rest coll)), (rest (first coll)), and (rest (rest coll)), respectively.

(second coll)

(first (rest coll)).

(every? pred coll)

Returns true if (pred x) is logical true for every x in coll, else false.

(not-every? pred coll)

Returns false if (pred x) is logical true for every x in coll, else true.

(some pred coll)

Returns the first logical true value of (pred x) for any x in coll, else nil.

(not-any? pred coll)

Returns false if (pred x) is logical true for any x in coll, else true.

(concat colls*)

Returns a lazy seq representing the concatenation of the elements in colls.

(map f colls+)

Returns a lazy seq consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments.

(mapcat f colls+)

Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection.

(reduce f coll)

f should be a function of 2 arguments. Returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called.

(reduce f val coll)

f should be a function of 2 arguments. Returns the result of applying f to val and the first item in coll, then applying f to that result and the 2nd item, etc. If coll contains no items, returns val and f is not called.

(filter pred coll)

Returns a lazy seq of the items in coll for which (pred item) returns true.

(take n coll)

Returns a lazy seq of the first n items in coll, or all items if there are fewer than n.

(take-nth n coll)

Returns a lazy seq of every nth item in coll.

(take-while pred coll)

Returns a lazy seq of successive items from coll while (pred item) returns true.

(drop n coll)

Returns a lazy seq of all but the first n items in coll.

(nthrest coll n)

Returns the nth rest of coll, (seq coll) when n is 0.

(drop-while pred coll)

Returns a lazy seq of the items in coll starting from the first item for which (pred item) returns nil.

(reverse coll)

Returns a seq of the items in coll in reverse order.

(cycle coll)

Returns a lazy (infinite!) seq of repetitions of the items in coll.

(interleave colls+)

Returns a lazy seq of the first item in each coll, then the second etc.

(split-at n coll)

Returns a vector of [(take n coll) (drop n coll)]

(split-with pred coll)

Returns a vector of [(take-while pred coll) (drop-while pred coll)]

(repeat x)

Returns a lazy (infinite!) seq of xs.

(replicate n x)

Returns a lazy seq of n xs.

(iterate f x)

Returns a lazy seq of x, (f x), (f (f x)) etc.

(range end)

(range start end)

(range start end step)

Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0 and step to 1.

(into to-coll from-coll)

Returns a new coll consisting of to-coll with all of the items of from-coll conjoined.

(distinct coll)

Returns a lazy sequence of the elements of coll with duplicates removed

(set coll)

 Returns a set of the distinct elements of coll.

(for [binding-form coll-expr ...] where-expr? expr)

Macro.

List comprehension. Takes one or more binding-form/collection-expr pairs, an optional filtering (where) expression, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms.


(take 10 (for [x (range 100) y (range 100) z [1 2 3]] (> x y z)
           [x y z]))
-> ([3 2 1] [4 2 1] [4 3 1] [4 3 2] [5 2 1] [5 3 1] [5 3 2] [5 4 1] [5 4 2] [5 4 3])

(doseq binding-form coll & body)

Macro. Repeatedly executes body (presumably for side-effects) with binding-form bound to successive items from coll. Does not retain the head of the sequence. Returns nil.

(scan seq)

(touch seq)

When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. scan and touch can be used to force any effects. Each walks through the successive rests of the seq. scan does not retain the head and returns nil, while touch retains the head and returns it (thus causing the entire seq to reside in memory at one time).

(sort coll)

(sort comparator coll)

Returns a sorted sequence of the items in coll. If no comparator is supplied, the items must implement Comparable. comparator must implement java.util.Comparator.

(sort-by keyfn coll)

(sort-by keyfn comparator coll)

Returns a sorted sequence of the items in coll, where the sort order is determined by comparing (keyfn item). If no comparator is supplied, the keys must implement Comparable. comparator must implement java.util.Comparator.

(zipmap keys vals)

Returns a map with the keys mapped to the corresponding vals.

(fnseq first restfn)

Returns a seq object whose first is first and whose rest is the value produced by calling restfn with no arguments. restfn will be called at most once per step in the sequence, e.g. calling rest repeatedly on the head of the seq calls restfn once - the value it yields is cached.

(lazy-cons first-expr rest-expr)

Macro. Expands to code which produces a seq object whose first is first-expr (evaluated) and whose rest is rest-expr, which is not evaluated until rest is called. rest-expr will be evaluated at most once per step in the sequence, e.g. calling rest repeatedly on the head of the seq evaluates rest-expr once - the value it yields is cached.

(lazy-cat seq-expr+)

Macro. Expands to code which yields a lazy sequence of the concatenation of the supplied sequences. Each sequence expr is not evaluated until it is needed.

(when-first binding-form coll exprs*)

Macro. Same as (when (seq coll) (let [binding-form (first coll)] exprs))

Copyright © Rich Hickey