Understand Clojure lists as immutable head-first sequences, code forms, and occasional data structures, while avoiding Java List assumptions about indexed access.
Clojure lists are not the default “list of things” for application data. Vectors usually fill that role. Lists matter because Clojure code itself is written as lists, and because lists are efficient at adding and reading from the front.
Java engineers should avoid mapping “Clojure list” directly to java.util.List. The name is familiar, but the performance profile and idioms are different.
| Use | Why lists fit | Better alternative when |
|---|---|---|
| Code forms | Clojure code is list-shaped | You are modeling domain data |
| Stack-like head operations | first, rest, and conj at the front are natural |
You need indexed access |
| Recursive examples | Head/tail decomposition is simple | Input depth is large or unbounded |
| Macro and tooling work | Lists represent unevaluated forms | You are just storing ordered values |
Use quote when you want literal list data without evaluation:
1'(1 2 3)
2;; => (1 2 3)
Use list when values should be evaluated first:
1(def x 10)
2
3(list x (+ x 1))
4;; => (10 11)
Without quote, a list in function position is evaluated as a call:
1(+ 1 2 3)
2;; => 6
That is the key syntax fact: parentheses usually mean “evaluate this form,” not “make a list.”
Lists are efficient at the front:
1(def xs '(1 2 3))
2
3(first xs)
4;; => 1
5
6(rest xs)
7;; => (2 3)
8
9(conj xs 0)
10;; => (0 1 2 3)
conj adds where the collection can accept efficiently. For lists, that is the front. For vectors, it is the end.
You can use nth on a list, but it walks through the list:
1(nth '(10 20 30) 2)
2;; => 30
If your Java code would call list.get(i) repeatedly, a Clojure vector is usually the better collection.
Lists work with ordinary sequence functions:
1(map inc '(1 2 3))
2;; => (2 3 4)
3
4(filter odd? '(1 2 3 4))
5;; => (1 3)
6
7(reduce + '(1 2 3 4))
8;; => 10
Remember that map and filter return lazy sequences. If you need a concrete vector, say so:
1(mapv inc '(1 2 3))
2;; => [2 3 4]
| Java habit | Clojure list reality |
|---|---|
ArrayList as default ordered data |
Prefer vectors |
LinkedList for queue-like work |
Consider persistent queues, vectors, or dedicated libraries depending on access pattern |
list.get(i) |
Use vectors for indexed access |
Mutating with add |
Use conj and keep the returned value |
| Iterator loops | Use sequence functions or reduce |
'(1 2 3) and (list 1 2 3) and explain the difference.(conj '(1 2 3) 0) with (conj [1 2 3] 0).List.get(i) loop using a vector.first and rest.conj adds to the front of a list.ArrayList; vectors usually are.