In JVM Clojure, Exceptions are for operating errors ("something went wrong") and Assertions are for programmer and correctness errors ("this program is wrong").
An assert
might be the right tool if throwing an Exception isn't enough. Use
them when the assertion failing means
- there's a bug in this program (not a caller)
- what happens next is undefined
- recovery is not possible or desired
Use assert
when its condition is so important you want your whole program to
halt if it's not true. (Note for library authors: this is a high bar, because
the program isn't yours.)
An assertion is not the orthodox tool for...
- checking arguments to a public function
- note:
defn
's:pre
and:post
are assertions
- note:
- validating web requests, user data, or similar
Asserts are for "this should never happen" situations, not run-of-the-mill failures.
- catching logically-impossible situations
- checking that the program is written correctly
- ensuring invariants hold
- validating assumptions at dev time without affecting production performance (optional)
- building part of a system in a design-by-contract style
- e.g. in internal code, testing conditions that you believe will be true no matter what a client does
- this is one intended use case for
:pre
/:post
-conditions
Oracle's Java documentation, Programming With Assertions
While the assert construct is not a full-blown design-by-contract facility, it can help support an informal design-by-contract style of programming.
John Regehr, Use of Assertions:
An assertion is a Boolean expression at a specific point in a program which will be true unless there is a bug in the program. This definition immediately tells us that assertions are not to be used for error handling. In contrast with assertions, errors [JVM Exceptions -ed.] are things that go wrong that do not correspond to bugs in the program.
Ned Batchelder, Asserts:
ASSERT(expr)
Asserts that an expression is true. The expression may or may not be evaluated.
- If the expression is true, execution continues normally.
- If the expression is false, what happens is undefined.
Tiger Beetle, Tiger Style:
Assertions detect programmer errors. Unlike operating errors, which are expected and which must be handled, assertion failures are unexpected. The only correct way to handle corrupt code is to crash. Assertions downgrade catastrophic correctness bugs into liveness bugs. Assertions are a force multiplier for discovering bugs by fuzzing.
- "Ceci n'est pas une Error" section in my Idiomatic errors in Clojure article
In your comments above, @daveliepmann , I wonder if there might be some ambiguity over the term "input". If the "input" is directly sourced external to the program the developer controls, then "bad input" is not obviously a program error and proper reporting by the dev's program is valuable. But if the "input" has been sourced internal to the program the developer controls, or it has been sourced externally and then modified by the program the developer controls, then "bad input" is a probably developer error and error recovery is unlikely.
From what I read above, these two interpretations of "input" get at the heart of the discussion above and bear heavily on the suitability of assertions as a means of signalling "bad input."
Somewhere there may be an analogy with the security mechanisms in place in some languages to manage the "taint" of externally-sourced data.