The seq abstraction
Intermediateseq is the way Clojure unifies everything that can be walked one item at a
time under a single interface. Vectors, lists, maps, sets, strings, ranges,
file lines, even custom types — all become logical lists with first,
rest, and cons. Code written against seq works on any of them.
A second feature comes almost for free: most seqs are lazy. (range)
gives you an infinite sequence; nothing is produced until something asks.
Minimal example
seq projects any collection into its sequence view. Notice that a map seqs
into a sequence of key-value pairs:
first and rest work the same on all of them — that's the abstraction:
Laziness
A lazy seq promises elements but doesn't realize them until needed. range
with no argument is an infinite seq; take decides how much of it to actually
produce:
You can chain transformations over an infinite seq because nothing has to be computed eagerly:
The pipeline reads as a recipe; only the final take pulls five values, and
each upstream step produces only enough output to satisfy that demand.
Practical example
Because seqs are uniform and lazy, the same pipeline works on data of any shape or size. Here it's a finite collection; switch to a stream of log lines or a database cursor, the code does not change.
Check yourself
? quiz
What does `(take 3 (range))` return, and why doesn't it loop forever?
Exercise
Write a single pipeline that yields the first five even squares, using only
map, filter, and take (no explicit recursion, no indices).