Clojureのdestructuringはベクターやmapの中から要素を取り出すのに、とても便利な機能。
さて、Clojure - Destructuring in Clojureに書いてあることなのだが、手を動かして確かめてみる。
使えるところ
関数
(defn foo [] (...))
無名関数
(fn [] (...))
let文
(let [] (...))
引数がベクターのとき
通常の使用方法
(def a [1 2]) (let [[x y] a] (println y "," x)) ; 結果 => 2,1
展開もとの要素数が足りない場合は、nilが代入される
(def b [1]) (let [[x y] b] (println y "," x)) ; 結果 => nil,1
_
を使って一部のみを取り出す
(def a [1 2]) (let [[_ y] a] (println y)) ; 結果 => 2
ベクターの入れ子もOK
(def abc [1 [2 3]]) (let [[x [y z]] abc] (println z "," y "," x)) ; 結果 => 3,2,1
ってどこまでOKなんだろう?
(def abcdefg [1 [2 3 [4 5 [6 7]]]]) (let [[_ [_ _ [_ _ [x y]]]] abcdefg] (println x "," y)) ; 結果 => 6,7
ひゅ〜、かっこいいね。
:as
を使って全体も扱う
(def abc [1 2 3]) (let [[x y :as z] abc] (println x "," y "<=" z)) ; 結果 => 1,2 <=[1,2,3]
&
を使って要素の一部を残りとして扱う
(def abc [1 2 3]) (let [[x & y] abc] (println x "," y)) ; 結果 => 1,(2 3)
引数がmapのとき
個別にkeyを指定して取り出す
(def mab {:a 1 :b 2}) (let [{x :a y :b} mab] (println y "," x)) ; 結果 => 2,1
展開時の{}
の書き方は、keyと要素が逆順、おしゃれ。
個別にkeyを指定して取り出す、特定のものだけ
(def mab {:a 1 :b 2}) (let [{z :b} mab] (println z)) ; 結果 => 2
ふーむ、便利。
存在しないkeyを指定した場合はnilが代入される
(def mab {:a 1 :b 2}) (let [{z :c} mab] (println z)) ; 結果 => nil
短縮形
(def mab {:a 1 :b 2}) (let [{:keys [a b]} mab] (println a "," b)) ; 結果 => 1,2
:keys
にkeywordの一覧を渡す。keywordから':‘を除いたものだね。これは要素がたくさんあるときは簡潔に表現できて便利。
mapのkeyにkeywordを使った場合はこのkeys
で指定できるが、keyに文字列やシンボルを使った場合は、:strs
、:syms
を使えば同じようにできる。すばらしすぎるな。
デフォルト値を入れることができる!
(def mab {:a 1 :b 2}) (let [{x :a, y :b, z :c :or {z 2}} mab] (println x "," y, "," z)) ; 結果 => 1,2,2
:c
はもともと定義したmapにはない要素だが、デフォルト値2を設定。
短縮形では、
(def mab {:a 1 :b 2}) (let [{:keys [a b c] :or {c 2}} mab] (println a "," b, "," c)) ; 結果 => 1,2,2
さらにmapの場合にも:as
が使える。
今日はここまで。