Programmer's Note

コード読み書きの備忘録。

Clojureのdestructuringメモ

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が使える。

今日はここまで。