Clojure Sequences Guide — Map, Filter, Reduce, and Lazy Sequences
In this tutorial, you will learn about Clojure Sequences Guide. We cover key concepts, practical examples, and best practices to help you master this topic.
Clojure sequences are a logical abstraction over collections with lazy evaluation -- map, filter, take, drop, and reduce operate on the seq interface, enabling composable data processing pipelines that compute only what's needed, when needed.
Core Sequence Functions
;; Map: transform each element
(map #(* % %) [1 2 3 4 5])
;; (1 4 9 16 25)
;; Filter: select matching elements
(filter even? (range 1 10))
;; (2 4 6 8)
;; Remove: opposite of filter
(remove even? (range 1 10))
;; (1 3 5 7 9)
;; Reduce: accumulate
(reduce + [1 2 3 4 5])
;; 15
(reduce + 100 [1 2 3])
;; 106 (with initial value)
Lazy Sequences
;; Infinite sequences
(take 5 (range)) ;; (0 1 2 3 4)
(take 10 (repeat 42)) ;; (42 42 42 ...)
(take 5 (cycle [1 2 3])) ;; (1 2 3 1 2)
(take 10 (iterate inc 0)) ;; (0 1 2 ... 9)
;; Lazy-seq for custom lazy sequences
(defn fib-seq
([] (fib-seq 0 1))
([a b] (cons a (lazy-seq (fib-seq b (+ a b))))))
(take 10 (fib-seq)) ;; (0 1 1 2 3 5 8 13 21 34)
Sequence Manipulation
;; Take and drop
(take 3 [1 2 3 4 5]) ;; (1 2 3)
(drop 3 [1 2 3 4 5]) ;; (4 5)
(take-last 2 [1 2 3 4]) ;; (3 4)
;; Split
(split-at 3 [1 2 3 4 5]) ;; [(1 2 3) (4 5)]
(split-with #(< % 3) [1 2 3 4]) ;; [(1 2) (3 4)]
;; Partition
(partition 2 [1 2 3 4]) ;; ((1 2) (3 4))
(partition-all 3 [1 2 3 4 5]) ;; ((1 2 3) (4 5))
Transforming Sequences
;; Flatten
(flatten [[1 2] [3 [4 5]]]) ;; (1 2 3 4 5)
;; Interleave and interpose
(interleave [1 2 3] [:a :b :c]) ;; (1 :a 2 :b 3 :c)
(interpose ", " [1 2 3]) ;; (1 ", " 2 ", " 3)
;; Group by
(group-by :age [{:name "A" :age 30} {:name "B" :age 30}])
;; {30 [{:name "A"} {:name "B"}]}
;; Frequencies (count occurrences)
(frequencies [1 2 1 3 2 1]) ;; {1 3, 2 2, 3 1}
Common Mistakes
1. Not using lazy sequences effectively
(map f (range)) works because map is lazy. But (vec (map f (range))) hangs (forces infinite seq).
2. Multiple traversals
(count (filter pred coll)) traverses once. (and (some pred coll) (every? pred coll)) traverses twice.
3. Realizing the entire sequence
Lazy seqs are only realized as needed. Functions like sort, count, and vec force the entire seq.
Practice Questions
1. What does (take 5 (range)) return?
(0 1 2 3 4) -- range with no args is an infinite lazy sequence starting from 0.
2. How do you create a lazy sequence?
Use lazy-seq: (cons x (lazy-seq (more))). Or use iterate, cycle, repeat.
3. What does reduce do?
(reduce f init coll) applies f to init and first element, then result and next element, etc.
FAQ
{{< faq question="What is the seq abstraction?" >}}
seq is a logical view of a collection. (seq coll) returns a seq or nil. Any collection supporting first/rest/cons works with seq functions.
{{< /faq >}}
{{< faq question="Are all Clojure sequences lazy?" >}}
Most sequence functions (map, filter, take) are lazy. But sort, frequencies, group-by are not.
{{< /faq >}}
{{< faq question="What is the difference between map and for?" >}}
map applies a function. for is a list comprehension with bindings and filters: (for [x [1 2] y [:a :b]] [x y]).
{{< /faq >}}
What's Next
Now learn about macros in Clojure.
| Topic | Description | Link |
|---|---|---|
| Macros | Macro programming | {{< ref "07-macros" >}} |
| State | Atoms, Refs, and Agents | {{< ref "08-state" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro