Skip to content

Instantly share code, notes, and snippets.

@daveliepmann
Last active March 2, 2025 12:24
Show Gist options
  • Save daveliepmann/8289f0ee5b00a5f05b50379e07fceb76 to your computer and use it in GitHub Desktop.
Save daveliepmann/8289f0ee5b00a5f05b50379e07fceb76 to your computer and use it in GitHub Desktop.
A guide to orthodox use of assertions in Clojure.

When to use assert?

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.)

Bad use cases for assert

An assertion is not the orthodox tool for...

  • checking arguments to a public function
    • note: defn's :pre and :post are assertions
  • validating web requests, user data, or similar

Asserts are for "this should never happen" situations, not run-of-the-mill failures.

Good use cases for assert

  • 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

References

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.

Further resources

@daveliepmann
Copy link
Author

daveliepmann commented Dec 8, 2024

@daveliepmann If I understood your take, you'd suggest that you don't throw AssertionErrors at all, and you avoid using assertions altogether, especially in library code. Or at least limit their use to private functions.

No, your statements about my take are not correct. I'm in favor of throwing AssertionErrors and of using assertions in library code. I'm just trying to be a stickler for the proper semantics of assertions. I'm mostly not taking a stance on how they should behave or be treated, such as enabling or not in prod or whether to crash or handle them. (Most of your last two comments seem to be about their behavior, not semantics, except maybe your last paragraph.)

I'm not even saying that only private functions should have assertions. I do say that the semantics of assertions do not include checking input arguments to a public function. (And "public function" has a fuzzy meaning in Clojure that you and I seem to differ on.) That public function could still make other kinds of assertions, such as asserting properties of internal data structures after input validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment