Search code examples
clojureassertionsassertiondesign-by-contract

Clojure condition-map parameter provided as metadata of the arglist


In the the special forms Clojure documentation (http://clojure.org/special_forms)

The condition-map parameter is described as below:

The condition-map parameter may be used to specify pre- and postconditions for a function. It is of the following form:

{:pre [pre-expr*] :post [post-expr*]}

where either key is optional. The condition map may also be provided as metadata of the arglist.

I can add the condition-map as a block to a (defn [x ] {:pre [] :post []}...) just fine, but I don't quite understand the comment about being able to provide the condition-map as metadata of the arglist.

I'm very new to Clojure, and have only just started learning about metadata. Can someone give an example of how this would be done?

Thanks,

Matt.


Solution

  • (defn foo ^{:pre [(even? x)] :post [(pos? %)]} [x]
      ;;      <-- metadata attached to arglist --> \ /
      ;;                                            |
      ;;                               arglist -----/
      (inc x))
    

    Calling the above the REPL:

    user=> (foo 0)
    1
    user=> (foo -2)
    AssertionError Assert failed: (pos? %)  user/foo (NO_SOURCE_FILE:2)
    user=> (foo 1)
    AssertionError Assert failed: (even? x)  user/foo (NO_SOURCE_FILE:2)