clojure 재 구성 (clojure destructuring)

4796 단어
재 구성 이 뭐 예요?
맵, list, struct 등 은 데이터 구 조 를 구성 한 것 으로 볼 수 있다.어떻게 이런 구조 안의 데 이 터 를 취 합 니까?그러면 구 조 를 뜯 어서 데 이 터 를 찾 아야 한다.이것 이 바로 재 구성 (destructuring) 이다.
왜 재 구성 을 해 야 합 니까?
clojure 에서 first, last, nth 등 함수 에 만 집합 하면 포 함 된 집합 요 소 를 간결 하 게 얻 을 수 없 기 때문에 destructuring 이 필요 합 니 다.
clojure 의 해체
clojure 가 지원 하 는 구 조 는 순서 집합 (sequential collection) 의 해체 와 맵 의 해체 가 있 습 니 다.
1. Sequential destructuring
질서 있 는 집합 포함:
    clojure 의 list, vector 및 sequence.
    java. util. List 인 터 페 이 스 를 실현 하 는 모든 집합
    자바 배열
    문자열
1. 위치 대응 에 따라 재 구성

(def v [42 "foo" 99.2 [5 12]])
(let [[x y z] v]
  (+ x z))
;= 141.2

;;       
(let [[x _ _ [y z]] v] 
  (+ x y z))
;= 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 (+ x z)))
;= [42 "foo" 99.2 [5 12] 141.2]

2. 지도 구조 화
맵 해 체 를 할 수 있 는 유형 은 다음 과 같 습 니 다.
  clojure hash-map,array-map,record。
  java. util. Map 인 터 페 이 스 를 실현 하 는 모든 집합
  get 함수 가 해당 값 을 가 져 오 는 대상 을 지원 합 니 다. 예 를 들 어 clojure vector, string, array
 
1. 위치 대응 으로 재 구성

(def m {:a 5 :b 6 
        :c [7 8 9] 
        :d {:e 10 :f 11}
        "foo" 88
        42 false})
;;  :  key   :key  ,        
(let [{a :a b :b} m] 
  (+ a b))
;= 11

;;  :     、    vector,   key   
(let [{x 3 y 8} [12 0 0 -18 44 6 0 0 1]] 
  (+ x y))
;= -17

;;     map    
(let [{[x _ y] :c} m] 
  (+ x y))
;= 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. 기본 값 (기본 값)

(let [k :unkown x :a 
       :or {k 50}
       m]
  (+ k x))
;;= 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 등에 사용 해도 된다.

(defn foo [{:keys [name age ] :as opts}] 
  (println name ":" age ))
;;  
(foo :name "hello" :age 20)
;=ArityException Wrong number of args (4) passed to: core$foo  clojure.lang.AFn.throwArity (AFn.java:437)
;;  
(foo {:name "hello" :age 20})
;=hello : 20

(defn foo2 [& {:keys [name age] 
                      :or {name "peter" age "18"} 
                      :as opts}] 
  (println name ":" age))
;;  
(foo2 {:name "hello" :age 20})
;;=IllegalArgumentException No value supplied for key: ......
;;  
(foo2)
;;=peter : 18
(foo2 :name "peter2" :age 20)
;;=peter2 : 20

이것 을 이용 하여 쓸 수 있 는 DSL 스타일 의 코드 는 가 독성 이 매우 좋 을 것 이다.

좋은 웹페이지 즐겨찾기