Jump to content

Learning Clojure/Destructuring

From Wikibooks, open books for an open world

The special forms let, loop, and fn are actually macros: the real special forms are named let*, loop*, and fn*. The macros are most commonly used in place of the actual special forms because the macros add a convenience feature called destructuring.

Often a function expects to receive a collection argument out of which it means to use particular items:

; return the sum of the 1st and 2nd items of the sequence argument
(defn foo [s]
   (+ (first s) (frest s))) ; sum the first item and the "frest" (first of the rest) item

Having to extract out the values we want can get quite verbose, but using destructuring can help in many cases:

; return the sum of the 1st and 2nd items of the sequence argument
(defn foo [s]
  (let [[a b] s]
    (+ a b)))

Above, where a parameter name is normally specified in the argument list, we put a vector followed by a parameter name: the items in the collection passed to the parameter s are bound to the names a and b in the vector according to position. Similarly, we can destructure using a map:

(def m {:apple 3 :banana 5})
(let [{x :apple} m]            ; assign the value of :apple in m to x
   x)                          ; return x

[I have to say this feels backwards to me: shouldn't it be (let [{:apple x} m] x)? I like to think of the destructuring expression as mirroring the collection being destructured.]

Destructuring can also be used to pull out the value of collections within collections. Hickey gives more complete coverage here.