5

In clojure I am using :pre like this

user=> (defn cannot-take-empty [x] {:pre [((complement empty?) x)]} 1)
#'user/cannot-take-empty
user=> (cannot-take-empty #{})
AssertionError Assert failed: ((complement empty?) x)  user/cannot-take-empty (NO_SOURCE_FILE:186)

That's great, but it doesn't explain the business reason why it doesn't make sense to pass in an empty collection. (Or a collection with more than five elements, or a collection that has two keys present but not another, or whatever the rule of the day is.) This is potentially even more confusing for the user if the precondition uses a private function.

Is there a way to provide more useful feedback to the user like an error message, when using :pre and :post?

George Simms
  • 3,930
  • 4
  • 21
  • 35
  • take a look at [this answer](http://stackoverflow.com/a/24874961/642340) It's a bit ugly but should work. – soulcheck Jun 06 '15 at 22:04
  • @soulcheck I was hoping to avoid explicitly throwing exceptions, it seems rather java-esque. – George Simms Jun 06 '15 at 22:06
  • you could always wrap it in a function/macro `(defn wrapper [c text] (if (not c) (throw (AssertionError. text))))` but yeah, not nice. – soulcheck Jun 06 '15 at 22:22

1 Answers1

4

Apparently pre and post conditions are designed for usecases where reporting the clauses provides enough information to the developer, i.e. it is self-explanatory. If you wish to provide more explanation, it is idiomatic to use assert.

But you can abuse the fact that the whole condition is always reported e.g. like this:

{:pre [(do "It can't be empty because of..."
           (seq x))]}

And it will report something like

AssertionError Assert failed: (do "It can't be empty because of..." (seq x)) ...

Leon Grapenthin
  • 9,246
  • 24
  • 37