CodeToLive

Clojure Sequences

Sequences are a fundamental abstraction in Clojure that provide a uniform way to work with collections. Clojure's sequence library includes powerful tools for lazy evaluation and functional transformations.

Sequence Basics

All Clojure collections can be treated as sequences:


(seq [1 2 3])    ; => (1 2 3)
(seq #{1 2 3})   ; => (1 3 2) (order varies)
(seq {:a 1 :b 2}) ; => ([:a 1] [:b 2])
                

Lazy Sequences

Clojure can create infinite sequences that evaluate only when needed:

range


(take 5 (range)) ; => (0 1 2 3 4)
                

repeat


(take 3 (repeat "x")) ; => ("x" "x" "x")
                

cycle


(take 5 (cycle [1 2 3])) ; => (1 2 3 1 2)
                

iterate


(take 5 (iterate inc 0)) ; => (0 1 2 3 4)
                

Common Sequence Functions

map


(map inc [1 2 3]) ; => (2 3 4)
(map + [1 2 3] [4 5 6]) ; => (5 7 9)
                

filter


(filter even? (range 10)) ; => (0 2 4 6 8)
                

remove


(remove even? (range 10)) ; => (1 3 5 7 9)
                

take/drop


(take 3 (range 10)) ; => (0 1 2)
(drop 3 (range 10)) ; => (3 4 5 6 7 8 9)
                

take-while/drop-while


(take-while #(< % 5) (range 10)) ; => (0 1 2 3 4)
(drop-while #(< % 5) (range 10)) ; => (5 6 7 8 9)
                

Sequence Processing

concat


(concat [1 2] [3 4]) ; => (1 2 3 4)
                

interleave


(interleave [:a :b :c] [1 2 3]) ; => (:a 1 :b 2 :c 3)
                

interpose


(interpose "," ["a" "b" "c"]) ; => ("a" "," "b" "," "c")
                

partition


(partition 2 [1 2 3 4 5 6]) ; => ((1 2) (3 4) (5 6))
(partition 2 1 [1 2 3 4]) ; => ((1 2) (2 3) (3 4))
                

Reducing Sequences

reduce


(reduce + [1 2 3 4]) ; => 10
(reduce max [3 1 4 2]) ; => 4
                

reductions


(reductions + [1 2 3 4]) ; => (1 3 6 10)
                

into


(into [] (map inc [1 2 3])) ; => [2 3 4]
                

Transducers

Efficient, composable sequence transformations:

Creating Transducers


(def xf (map inc))
(def xf2 (filter even?))
                

Using Transducers


(into [] xf [1 2 3]) ; => [2 3 4]
(transduce xf + 0 [1 2 3]) ; => 9
                

Composing Transducers


(def xf (comp (map inc) (filter even?)))
(into [] xf [1 2 3 4]) ; => [2 4]
                

Lazy Sequence Patterns

Generating Infinite Sequences


(def fib-seq
  (map first 
       (iterate (fn [[a b]] [b (+ a b)]) 
       [0 1]))

(take 10 fib-seq) ; => (0 1 1 2 3 5 8 13 21 34)
                

Chunking


; Clojure evaluates sequences in chunks of 32 for efficiency
(take 1 (map #(do (println %) %) (range 100)))
; Prints 0-31 due to chunking
                

Performance Considerations

  • Prefer into over repeated conj for building collections
  • Use transducers for efficient pipeline processing
  • Be mindful of chunking behavior with side effects
  • Consider doseq for side-effecting operations

Next Steps

Continue learning with: