Matthew Boston

Understanding Clojure: cond and condp

This is the first part of a multi-part series I want to start titled “Understanding Clojure”. Often times I come across Clojure code that can be refactored a bit better or even there’s an existing function to do X. Hopefully I can shine some light on some aspects of Clojure you didn’t know existed.

cond

(cond
  (> 0 (:amount account)) "Your balance is negative"
  (< 0 (:amount account)) "Your balance is positive"
  (= 0 (:amount account)) "Your balance is zero")

There is also the option of a default case using :else.

(cond
  (> 0 (:amount account)) "Your balance is negative"
  (< 0 (:amount account)) "Your balance is positive"
  :else "Your balance is zero")

condp

condp can be used if your predicate remains the same for each condition and you wish to switch on the result.

(condp < (:amount account)
  10000 "top tier dividend"
  5000 "second tier dividend"
  1000 "first tier dividend"
  0 "no dividend")

To supply an else condition to condp, you leave out the :else and supply the result expression.

(condp < (:amount account)
  10000 "top tier dividend"
  5000 "second tier dividend"
  1000 "first tier dividend"
  "no dividend")

You can also supply condp with your own predicate function.

(defn describe [amount]
  (cond
    (> 0 amount) :negative
    (< 0 amount) :positive
    :else :zero))

(defn compare [descriptor amount]
  (= descriptor (describe amount)))

(condp compare (:amount account)
  :negative "Your balance is negative"
  :positive "Your balance is positive"
  :zero "Your balance is zero")

The predicate function (compare) must take exactly two arguments and must return a binary result. The predicate function would be called like:

(compare :negative (:amount account))
(compare :positive (:amount account))
(compare :zero (:amount account))