Last Updated: February 25, 2016
·
508
· okal

Clojure Destructuring Gotcha

(defn hello
  [& {:keys [person]
      :or {person "Rich"}}]
      (str "Hello, " person))

(hello) => "Hello, Rich"

(hello :person "Hickey") => "Hello, Hickey"

I'd have expected (hello :person nil) to have the same result as calling (hello), but as it turns out, Clojure seems to make a distinction between nothing and nil when it comes to destructuring.

A real world situation where this might occur would be where you, for instance, rely on the result of a destructuring operation to provide parameters for a function similar to hello. e.g.

(defn spam
      [& {:keys [person]}]
      (str (hello :person person)
            "Give me all your money."))

Calling (spam) would result in (hello :person nil), which would have the - probably - unintended effect of returning "Hello, ". You may choose to add an :or when destructuring the argument to spam, but then you'll have the same code appearing twice. A more localised solution would be changing the hello definition to be something like this.

(defn hello
  [& {:keys [person]}]
      (str "Hello, " (or person "Rich")))

This worked for my case, but I'd love to hear about more idiomatic approaches.