[フレーム]
Last Updated: February 25, 2016
·
554
· 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.

AltStyle によって変換されたページ (->オリジナル) /