📝Clojure: 分配束縛(Destructuring)

📝Clojure: 分配束縛(Destructuring)

September 2, 2022

大きいテーマなので 📝Clojure Functional Programmingのサブジャンルとしてメモを分離.

Clojure分配束縛概要 #

Clojureでは分配束縛をサポートしている.

  • シーケンシャルとアソシエーティブなデータ構造の2つの種類がある.
    • Sequencial Destructuring: Vector構造を分解
    • Associative Destructuring: Map構造を分解
  • vectorの中にvectorやmapを書いて表現する.
    • [[][]]
    • [{}{}]
  • 分配束縛したくない変数はvectorなら:as, mapなら:or で表現する.
  • :keysをつかうと,mapをうけとったらその値をシンボルにバインドできる.

Clojure Basic Techniques #

一時変数(let)を分解するために分配束縛をつかう #

通常は let の中で使われる.

(def my-vector [:a :b :c :d])

(let [[a b c d] my-vector]
  (println a b c d))
;; => :a :b :c :d

関数の引数で分配束縛をつかう #

通常は [[][]]や[{}{}]のように書いて右から左にparseするが, 関数の引数として[[][]]を省略して[[]]とかける.

通常のbinding.

(defn foo [a b]
    (println a b))

(defn foo [a b & {:keys [x y]}]
  (println a b x y))
(foo "A" "B" :x "X" :y "Y")  ;; => A B X Y

余分なものはひとつにまとめるbinding.

(defn foo [a b & args]
    (println a b args))
(foo :a :b :x :y :z) ;; => :a :b (:x :y :z)

(defn foo [& {:as m}]
  (println m))
(foo :x "X" :y "Y") ;; => {:y Y, :x X}

keysで必要なものだけ取りつつ残りも取るよくばりパターン.

(defn foo [a b & {:keys [x y] :as m}]
  (println a b x y m))
(foo "A" "B" :x "X" :y "Y")
;; => A B X Y {:y Y, :x X}

この記法(keyword引数にmapを指定)はClojure 1.11からのサポートなのかな?

Clojure - Keyword argument functions now also accept maps

この書き方はつかえそう.

(defn some-handler [{:keys [db,,,,] :as req}]
,,)

奥が深い…

see also: 関数の引数にデフォルト値を指定するには?

Mapのkeyword以外のバラし方(:strs/:syms) #

:keysがあまりにも登場機会がおおい気がするが, 分配束縛はkeyword以外にも文字列やシンボルで利用可能.

文字列は :strs, シンボルは :syms でそれぞれ分解する.

Clojure Destructureing Tips #

分配束縛のテクニックをClojureで使いこなせるとモテるとか誰かが言ってた.

📝Clojure Tips

ネストしたMapを分配束縛でバラせるか? #

殺れます!

(def my-nested-hashmap {:a "A" :b "B" :c "C" :d "D"
                        :q {:x "X" :y "Y" :z "Z"}})

(let [{:keys [a b] {:keys [x y]} :q} my-nested-hashmap]
  (println a b x y))

しかし若干の読みにくさがあるので無理ないほうがいいかも.

🔗 Rerefences #


Tags