On Github kaosf / 20140216-clojure-destructuring
Clojure における関数の引数の妙技
(Common Lisp でもあるはず)
(def p1 [10 20]) (def p2 [30 40])
座標を表すものをこのように管理して
(defn distance [p1 p2] (let [dx (- (nth p1 0) (nth p2 0)) dy (- (nth p1 1) (nth p2 1))] (Math/sqrt (+ (* dx dx) (* dy dy))))) (distance p1 p2) ;-> 28.284271247461902 ; 20√2
としたりすることがある
(- (nth p1 0) (nth p2 0)) (- (nth p1 1) (nth p2 1))
(defn distance [[x1 y1] [x2 y2]] (let [dx (- x1 x2) dy (- y1 y2)] (Math/sqrt (+ (* dx dx) (* dy dy)))))
(defn f [x y] ...) (f 1 2) ; call ; ~ ~ ; | | ; V V (f [x y])
(defn f [x y] ...) (f [1 2] [3 4]) ; call ; ~~~~~ ~~~~~ ; | | ; V V (f [x y])
(defn f [[x1 x2] [y1 y2]] ...) (f [1 2] [3 4]) ; call ; ~ ~ ~ ~ ; | | | | ; V V V V (f [[x1 x2] [y1 y2]])
そのままの形で受け取って名前も決められる
マップを受け取る
(defn f [{x :a y :b}] ...) (f {:a 1 :b 2}) ; call ; ~ ~ ; | | ; V V (f [{ x :a y :b}])
マップのキーがキーワードの場合
キーワードから : を除いたシンボル名を変数にする
(defn f [{:keys [x y]}] ...) (f { :x 1 :y 2}) ; call ; ~ ~ ; | | ; V V (f [{:keys [x y]}] ...)
:keys という特別な指定が出来る
マップのキーがキーワードの場合は :keys
シンボルの場合は :syms
文字列の場合は :strs
let は
(let [x ( ...(1)... ) y ( ...(2)... )] ...(3)... )
...(1)... の値に x が束縛され...(2)... の値に y が束縛され...(3)... の中で x y が使える
(let ...) 自体の評価結果は ...(3)... の評価結果になる
let はローカル変数を扱うような感覚
ここでも変数の束縛を行う
そのルールも関数の引数と同じ
(let [[x y] [1 2]] [y x]) ;-> [2 1] (let [{x :a} {:a 1}] x) ;-> 1 (let [{x :a} {:b 1}] x) ;-> nil (let [{x :a y :a} {:a 1 :b 2 :c 3}] [x y]) ;-> [1 1] (let [{:keys [x y]} {:a 1 :b 2}] [x y]) ;-> [nil nil] (let [{:keys [x y]} {:a 1 :b 2 :x 3 :y 4}] [x y]) ;-> [3 4]