Vector destructuring is the simplest form. It is similar to Python's list unpacking feature, but much more powerful.
Syntax: [symbol another-symbol] ["value" "another-value"]
(def my-vector [:a :b :c :d])
(def my-nested-vector [:a :b :c :d [:x :y :z]])
(let [[a b c d] my-vector]
(println a b c d))
;; => :a :b :c :d
(let [[a _ _ d [x y z]] my-nested-vector]
(println a d x y z))
;; => :a :d :x :y :z
You don't have to match the full vector.
(let [[a b c] my-vector]
(println a b c))
;; => :a :b :c
You can use & rest
to bind the remaining part of the vector to rest
.
(let [[a b & rest] my-vector]
(println a b rest))
;; => :a :b (:c :d)
When a destructuring form "exceeds" a vector (i.e. there not enough items in the vector to bind to), the excess symbols will be bound to nil
.
(let [[a b c d e f g] my-vector]
(println a b c d e f g))
;; => :a :b :c :d nil nil nil
You can use :as some-symbol
as the last two items in the destructuring form to bind the whole vector to some-symbol
(let [[:as all] my-vector]
(println all))
;; => [:a :b :c :d]
(let [[a :as all] my-vector]
(println a all))
;; => :a [:a :b :c :d]
(let [[a _ _ _ [x y z :as nested] :as all] my-nested-vector]
(println a x y z nested all))
;; => :a :x :y :z [:x :y :z] [:a :b :c :d [:x :y :z]]
You can use both & rest
and :as some-symbol
.
(let [[a b & rest :as all] my-vector]
(println a b rest all))
;; => :a :b (:c :d) [:a :b :c :d]
(defn foo [a b & [x y z]]
(println a b x y z))
(foo :a :b) ;; => :a :b nil nil nil
(foo :a :b :x) ;; => :a :b :x nil nil
(foo :a :b :x :y :z) ;; => :a :b :x :y :z
Hashmap destructuring is much more complicated, and can get quite verbose, but is much more powerful than vector destructuring.
Syntax: {symbol :key, another-symbol :another-key} {:key "value" :another-key "another-value"}
(def my-hashmap {:a "A" :b "B" :c "C" :d "D"}) (def my-nested-hashmap {:a "A" :b "B" :c "C" :d "D" :q {:x "X" :y "Y" :z "Z"}})
(let [{a :a d :d} my-hashmap] (println a d)) ;; => A D
(let [{a :a b :b {x :x y :y} :q} my-nested-hashmap] (println a b x y)) ;; => A B X Y
Similar to vectors, if a key is not found in the map, the symbol will be bound to nil
.
(let [{a :a not-found :not-found b :b :as all} my-hashmap] (println a not-found b all)) ;; => A nil B {:a "A" :b "B" :c "C" :d "D"}
You can provide an optional default value for these missing keys.
A