Destructuring is a functionality within Clojure, which allows one to extract values from a data structure, such as a vector and bind them to symbols without having to explicitly traverse the datastructure.
Let’s look at an example of what exactly Destructuring means and how does it happen.
(ns clojure.examples.example (:gen-class)) (defn Example [] (def my-vector [1 2 3 4]) (let [[a b c d] my-vector] (println a b c d))) (Example)
The above program produces the following output.
1 2 3 4
In the above example, following things are to be noted −
We are defining a vector of integers as 1 ,2, 3 and 4.
We are then using the ‘let’ statement to assign 4 variables (a, b, c, and d) to the my-vector variable directly.
If we run the ‘println’ statement on the four variables, we can see that they have already been assigned to the values in the vector respectively.
So clojure has destructured the my-vector variable which has four values when it was assigned using the ‘let’ statement. The deconstructed four values were then assigned to the four parameters accordingly.
If there are excess variables which don’t have a corresponding value to which they can be assigned to, then they will be assigned the value of nil. The following example makes this point clear.
(ns clojure.examples.hello (:gen-class)) (defn Example [] (def my-vector [1 2 3 4]) (let [[a b c d e] my-vector] (println a b c d e))) (Example)
The above program produces the following output. You can see from the output that since the last variable ‘e’ does not have a corresponding value in the vector, it accounts to nil.
1 2 3 4 nil
The ‘the-rest’ variable is used to store the remaining values, which cannot get assigned to any variable.
An example on how this is used is shown in the following program.
(ns clojure.examples.example (:gen-class)) (defn Example [] (def my-vector [1 2 3 4]) (let [[a b & the-rest] my-vector] (println a b the-rest))) (Example)
The above program produces the following output. From the output, you can clearly see that the values of 3 and 4 cannot be assigned to any variable so they are assigned to the ‘the-rest’ variable.
1 2 (3 4)
Just like vectors, maps can also be destructured. Following is an example of how this can be accomplished.
(ns clojure.examples.example (:gen-class)) (defn Example [] (def my-map {"a" 1 "b" 2}) (let [{a "a" b "b"} my-map] (println a b))) (Example)
The above program produces the following output. From the program you can clearly see that the map values of “a” and “b” are assigned to the variables of a and b.
1 2
Similarly in the case of vectors, if there is no corresponding value in the map when the destructuring happens, then the variable will be assigned a value of nil.
Following is an example.
(ns clojure.examples.example (:gen-class)) (defn Example [] (def my-map {"a" 1 "b" 2}) (let [{a "a" b "b" c "c"} my-map] (println a b c))) (Example)
The above program produces the following output.
1 2 nil