clojure解構(clojure destructuring)

【轉】http://rritw.com/a/JAVAbiancheng/JAVAzonghe/20130615/370731.html

由於在clojure中如果只靠一些集合到操作函數如first、last、nth等函數,不能夠簡潔的獲取一些嵌套集合中的元素,所以需要destructuring來使我們可以簡潔快速的去獲取集合中的元素。

由於在clojure中如果只靠一些集合到操作函數如first、last、nth等函數,不能夠簡潔的獲取一些嵌套集合中的元素,所以需要destructuring來使我們可以簡潔快速的去獲取集合中的元素。 clojure支持的結構有:有順序集合(sequential collection)的解構和map的解構。

 一、Sequential destructuring 有序集合包括:clojure的list,vector以及sequence。所有實現java.util.List接口的集合:java數組、字符串 

1、根據位置對應來解構

(def v [42 "foo" 99.2 [5 12]])
(let [[xyz] v]
  (+ xz))
;= 141.2

;;使用下劃線佔位
(let [[x _ _ [yz]] v] 
  (+ xyz))
;= 59

2、收集剩餘的元素(Gathering extra-positional sequential values​​) 
;;使用&來收集
(let [[x & rest] v] 
  rest)
;= ("foo" 99.2 [5 12])

3、保留解構的值(retaining the destructured value) 
;;使用as來保留解構的值
(let [[x _ z :as original-vector] v] 
  (conj original-vector (+ xz)))
;= [42 "foo" 99.2 [5 12] 141.2]


二、Map destructuring 可以進行map解構的類型有:   clojure hash-map,array-map,record。   所有實現java.util.Map接口的集合   支持get函數獲取相應值的對象,如:clojure vector,string,array1、位置對應來解構 

(def m {:a 5 :b 6 
        :c [7 8 9] 
        :d {:e 10 :f 11}
        "foo" 88
        42 false})
;;注意:這裏key不單是:key類型,也可以是其他類型
(let [{a :ab :b} m] 
  (+ ab))
;= 11

;;注意:如果是數組、字符串或vector,解構的key是下標
(let [{x 3 y 8} [12 0 0 -18 44 6 0 0 1]] 
  (+ xy))
;= -17

;;順序解構和map解構混合
(let [{[x _ y] :c} m] 
  (+ xy))
;= 16

(def map-in-vector ["James" {:birthday (java.util.Date. 73 1 6)}])
;= #'user/map-in-vector

(let [[name {bd :birthday}] map-in-vector]
  (str name " was born on " bd))
;= "James was born on Thu Feb 06 00:00:00 EST 1973"

2、保留解構的值(retaining the destructured value) 
和順序解構一樣用as來保存。 
(let [{r1 :x r2 :y :as randoms}
       (zipmap [:x :y :z] (repeatedly (partial rand-int 10)))]
(assoc randoms :sum (+ r1 r2)))
;= {:sum 17, :z 3, :y 8, :x 9}

3、默認值(Default values​​) 
(let [k :unkown x :a 
       :or {k 50}
       m]
  (+ kx))
;;= 55     

4、綁定值到對應的key上(binding values​​ to their key's name) 
;;這裏的可以用:keys、:strs、:syms來指定key的類型
;;但是通常使用:keys類型
;;在很多框架中,經常會看到:keys,:or,:as的組合使用
(def chas {:name "Chas" :age 31 :location "Massachusetts"}) 
(let [{name :name age :age location :location} chas]
  (format "%s is %s years old and lives in %s." name age location)) 
;= "Chas is 31 years old and lives in M​​assachusetts."

5、對剩餘部分像map一樣解構(Destructuring rest sequences as map key/value pairs) 
;;這個代碼太亂,有潔癖的人受不鳥
(def user-info ["robert8990" 2011 :name "Bob" :city "Boston"])
(let [[username account-year & extra-info] user-info
       {:keys [name city]} (apply hash-map extra-info)] 
  (format "%s is in %s" name city))
;= "Bob is in Boston"

;;如果剩餘部分的參數個數是偶數個的話,可以用map解構
;;有潔癖的人現在覺得世界清靜多了
(let [[username account-year & {:keys [name city]}] user-info] 
  (format "%s is in %s" name city))
;= "Bob is in Boston"


最後,雖然以上的例子只是用let,但是解構用在fn、defn等地方都是可以的。 
    

參考文檔:《clojure programming》 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章