Friday, October 28, 2016

Destructuring Clojure Vector and Map

Clojure documentation describes destructuring as:


Destructuring is a way to concisely bind names to the values inside a data structure. Destructuring allows us to write more concise and readable code.

So, what does this mean?

Suppose we have a vector that contains the bridge officers found in Star Trek original series:


(def star-trek-bridge-officers [ :kirk :spock :sulu :uhura ])

To retrieve the values, we could destructure the elements this way:


(let [[a b c d ] star-trek-bridge-officers] 
    println (str a " " b " " c " " d))
;; ":kirk :spock :sulu :uhura"

What happened here was the keyword :kirk is bound to the variable a, :spock to b and so on and so forth.


Suppose we have a slightly different vector, where :sulu and :uhura belongs to another subvector:


(def star-trek-bridge-officers-2 [ :kirk :spock [:sulu :uhura]])

To retrieve the values:


(let [[a b [c d]] star-trek-bridge-officers-2] println (str a " " b " " c " " d))
;; ":kirk :spock :sulu :uhura"

If we're not interested with Spock and Uhura, we replace the variables with underscore character "_":

(let [[a _ [c _]] star-trek-bridge-officers-2] 
    println (str a " " c))

;; ":kirk :sulu"



Jim, you can't risk your life on theory!



Now, let's talk about destructuring a map.

Suppose we have a map that contains the rank and names of the crew:


(def star-trek-crew { :captain "kirk" :lt-cmd "spock" :lt-1 "sulu" :lt-2 "uhura" })

To retrieve the values by the keys:


(let [{a :captain b :lt-cmd c :lt-1 d :lt-2 } star-trek-bridge-officers] 
    println (str a " " b " " c " " d))
;; "kirk spock sulu uhura"

The variable a is bound to the value of the key :captain and b is bound to the value of the key :lt-cmd.

To complicate the map structure a bit, I'm going to add a few more members as an embedded map:


(def star-trek-officers { :captain "kirk" :lt-cmd "spock" :lt-1 "sulu" :lt-2 "uhura" 
    :non-bridge-officers {:lt-cmd-1 "scotty" :lt-cmd-2 "mccoy" :nurse "chapel"}})

To retrieve the values including the embedded map:


(let [{a :captain b :lt-cmd c :lt-1 d :lt-2 {x :lt-cmd-1 y :lt-cmd-2 z :nurse} 
    :non-bridge-officers} star-trek-officers] 
        println (str a " " b " " c " " d " " x " " y " " z))
;; "kirk spock sulu uhura scotty mccoy chapel"

As you can see, we need to use :non-bridge-officers as the key to refer to the embedded map.


We all have our darker side. We need it; it's half of what we are.
        It's not really ugly, it's human.


No comments:

Post a Comment