Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active February 13, 2023 19:35
Show Gist options
  • Save Integralist/11376734 to your computer and use it in GitHub Desktop.
Save Integralist/11376734 to your computer and use it in GitHub Desktop.
Clojure destructuring using `let` (which allows local storage inside of a function, we would say a local "variable" but that would be misleading because all data is immutable in Clojure)

In Clojure you can apply destructuring within either a let binding list; function parameter list or even a macro.

A simple example would be:

(def coords [5 7]) ; define a symbol "coords" that points to a vector [5 7]
(let [[x y] coords] (println "x:" x "y:" y))
; => x: 5 y: 7

Another simple example (this time using the & rest operator) would be:

(def indexes [1 2 3])
(let [[x & more] indexes] (println "x:" x "more:" more))
; => x: 1 more: (2 3)

A complex example (which utilises :as e to assign the entire item being destructured into e):

(def indexes [1 2 3 4 5 6 7])
(let [[a b c & d :as e] indexes]
  [a b c d e])
; => [1 2 3 (4 5 6 7) [1 2 3 4 5 6 7]]

Although possible to do nested destructuring, it is advised not to nest as it can become too complex:

(def nested [[1 2][3 4]])
(let [[[x1 y1][x2 y2]] nested]
  [x1 x2 y1 y2])
; => [1 3 2 4]

Here is an example that uses :or to provide default values for keys that can't be found in the data being destructured (you'll notice that the b key wasn't provided and so we received the default value of 22 instead):

(def a-map {:a 1 :c 3})
(let [{a :a, b :b, c :c, :as original-data :or {a 11 b 22 c 33}} a-map]
  [a b c original-data])
; => [1 22 3 {:a 1, :c 3}]

In the following example we see the use of :keys as a shortcut way of not having to redefine the same keys ourselves (typically when destructuring data you'll end up saying something like "give me the value for key 'a' and just put it in this other place called 'a'" - so Clojure provides a shortcut for that). This example also demonstrates what happens if no default is provided:

(def a-map {:a 1 :c 3})
(let [{:keys [a b c]} a-map]
  [a b c])
; => [1 nil 3]

Nested map destructuring (whatever the type is - in this example a map - use that syntax to delve deeper into the structure):

(def test {:params {:foo "bar" :baz "qux"}})
(let [{{foo :foo} :params} test] 
  (prn foo))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment