Use predicates and assertions to express invariants clearly in Clojure without confusing local checks with full boundary validation.
Predicates answer yes-or-no questions about a value. Assertion functions use those predicates or related checks to state what must be true at a particular point in the program.
This sounds simple, but it is one of the most important habits in good Clojure code. Since so much of the language is data-oriented, correctness often depends on expressing invariants clearly:
Small, named predicates are often the clearest way to make those rules visible.
Predicates improve code for two reasons:
Compare these:
1(when (and (pos? amount) (not (:blocked? account))))
2 ...)
1(defn chargeable-account? [account amount]
2 (and (pos? amount)
3 (not (:blocked? account))))
4
5(when (chargeable-account? account amount)
6 ...)
The second form is easier to read, easier to reuse, and easier to test.
Assertions are not just reusable predicates with louder syntax. They usually express one of two ideas:
1(defn allocate-budget [amount]
2 (assert (pos? amount) "Budget allocation must be positive")
3 {:allocated amount})
That is appropriate when a negative amount indicates a programming or logic error. It is less appropriate when user input is expected to be messy and needs graceful validation.
This distinction is crucial.
Use boundary validation when external or user input can reasonably be wrong and the program should respond cleanly.
Use assertions when the code is checking an internal assumption that should already have been established.
Confusing the two leads to brittle systems:
Some of the best predicates in Clojure read like domain language:
active-user?retryable-error?final-state?authorized-request?These names do more than shorten code. They make the program tell the reader what distinction matters.
The first mistake is writing overly generic predicates that hide important domain distinctions.
The second mistake is scattering raw boolean expressions everywhere instead of naming important checks.
The third mistake is using assertions as a substitute for real validation at system boundaries.
Ask these when reviewing predicate and assertion usage:
Good predicate design makes programs read like they understand their own rules.