続Clojureのdestructuringメモ
前回「 Clojureのdestructuringメモ - Programmer's Note 」の続き。
マップのdestructuring
文字列をキーに使った場合を試す
(def mab {"a" 1 "b" 2}) (let [{:strs [a b]} mab] (println b "," a)) ; 結果 => 2,1
Goood!!
下記非短縮形もOK。
(def mab {"a" 1 "b" 2}) (let [{x "a" y "b"} mab] (println x y))
シンボルがキーの場合
(def mcd {'c 1 'd 2}) (let [{:syms [c d]} mcd] (println c "," d)) ; 結果 => 1,2
Goooooood!!
下記非短縮形もOK。
(def mcd {'c 1 'd 2}) (let [{x 'c y 'd} mcd] (println y "," x))
さて、マップの入れ子構造も試してみる
(def dat {:name "boo" :body {:weight 60 :height 160 } :money 100}) (let [{{h :height} :body} dat] (println h)) ; 結果 => 160
ベクターとマップの組み合わせ!
マップの中にベクターがある場合。
(def dat {:name "boo" :body [60 160] :money 100}) (let [{[_ height] :body} dat] (println height)) ; 結果 => 160
ベクターの中にマップがある場合。
(def dat ["boo" {:weight 60 :height 160} 100]) (let [[_ {h :weight} _] dat] (println h)) ; 結果 => 60
なんつービューティフルな言語なんだ!
関数に引数をマップで与える場合の省略形
たとえば関数にパラメータでマップを渡したい場合、
(boo "foo" {:weight 50 :height 120})
にするが、これを
(boo "foo" :weight 50 :height 120)
のように書ける!
前者の関数定義は
(defn boo [name opts] (let [{w :weight h :height} opts] (println name ": (" w "," h ")")))
で、後者は
(defn boo [name & opts] (let [{w :weight h :height} opts] (println name ": (" w "," h ")")))
違いは引数の定義に&
を使っているだけ!
defn
は実はマクロで、& opts
と定義したときは、残りの引数をまとめてシーケンスに入れてくれる。
さらにシーケンスはベクターにもマップにも展開できる。
シーケンスという一個上位の抽象概念をかますと、物事をシンプルに扱える。美しい。
destructuringは関数の引数定義[]
でも同じように使えるから、後者はこのようにも書ける。
(defn boo [name & {w :weight h :height}] (println name ": (" w "," h ")"))
いやあClojure最高です。