Stuart Sierra’s anti-patterns for Clojure

(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at:

This is a subtle difference:

Be explicit about your types even when they’re dynamic.

If the operation requires a collection, then pass it a collection every time.

A “helper” like wrap-coll saves you a whopping two characters over just wrapping the argument in a literal vector, at the cost of lost clarity and specificity.

If you often forget to wrap the argument correctly, consider adding a type check:

(defn process-batch [items]
  {:pre [(coll? items)]}
  ;; ...

If there actually are two distinct operations, one for a single object and one for a batch, then they should be separate functions:

(defn process-one [item]
  ;; ...

(defn process-batch [items]
  ;; ...

In another post he offers to flip side of the rule:

If you have an operation on a single object, you don’t need to define another version just to operate on a collection of those objects.

That is, if you have a function like this:

(defn process-thing [thing]
;; process one thing
There is no reason to also write this:

(defn process-many-things [things]
(map process-thing things))

The idiom “map a function over a collection” is so universal that any Clojure programmer should be able to write it without thinking twice.

In other words, write a function that does something with one item, and then write map to apply it to collections.