Use lens-like helpers only when nested immutable updates become repetitive enough to justify an abstraction in Clojure.
Lens: A reusable abstraction for focusing on part of a larger immutable structure so you can read or update that focus consistently.
The lens pattern is attractive because nested immutable updates can get repetitive. If your code frequently reaches into deeply nested maps, transforms one field, and rebuilds the larger structure, a reusable access/update abstraction can reduce duplication.
But this is also an area where Clojure developers often over-abstract too early. The language already has strong built-in tools for many cases: get-in, assoc-in, and update-in.
For many applications, plain nested update helpers are enough:
1(def order
2 {:id 42
3 :customer {:profile {:tier :silver
4 :email "user@example.com"}}})
5
6(update-in order [:customer :profile :tier] (constantly :gold))
That is already explicit, familiar, and easy to review.
The visual below shows the core idea:
flowchart LR
Root["Original nested map"] --> Focus["Focus on [:customer :profile :tier]"]
Focus --> Update["Apply update function"]
Update --> Result["New map with only the path rewritten"]
A lens-like helper becomes reasonable when you repeatedly need the same focus across multiple operations:
For example:
1(defn on-tier [f order]
2 (update-in order [:customer :profile :tier] f))
3
4(defn promote-tier [order]
5 (on-tier (constantly :gold) order))
This is not a full lens library, but it captures the useful part of the pattern: name the focus once, then reuse it.
In ecosystems where lenses are central, they support powerful composition of nested access paths. Clojure can do that too, but you should ask whether the abstraction cost is really paying for itself.
Lens-heavy code can become harder to read when:
update-in was already clearerThis is one of those patterns where local repetition is not automatically a defect. A little duplication may be easier to understand than a private algebra of getters and setters.
The core design question is not “can I use a lens here?” It is “does this make nested immutable work easier to review and change?”
Good signs:
Bad signs:
When reviewing lens-like abstractions in Clojure, ask:
get-in or update-in already enough?In many Clojure codebases, the best use of the lens pattern is modest: a few named focus helpers around important nested structures, not a wholesale replacement of ordinary data access.