【转】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 Massachusetts."
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》