(cljs/run - at (JSVM.: all) "한 번 에 하 얀 DataType, Record, Protocol")
5931 단어 clojurescript
프로젝트 에서 우 리 는 보통 실제 문제 영역 에 분야 데이터 모델 을 정의 합 니 다. 예 를 들 어 VDOM 을 개발 할 때 자 연 스 럽 게 VNode 데이터 형식 을 정의 하여 관련 데 이 터 를 포장 하고 저장 하 며 조작 하 는 데 사 용 됩 니 다.clj/cljs 는
List
, Vector
, Set
, Map
등 데이터 구 조 를 내장 하고 deftype
와 defrecord
를 제공 하여 실제 개발 수 요 를 만족 시 킬 수 있 도록 데이터 구 조 를 사용자 정의 할 수 있 습 니 다.데이터 구 조 를 정의 하려 면 Data Type 과 Record 부터 시작 합 니 다.
데이터 구 조 를 언급 하면 자 연 스 럽 게 C 언어 중의 struct 를 떠 올 린 다. 구조 에서 필드 만 정 의 된 방법 이 없고 이것 도
deftype
와 defrecord
가장 기본 적 인 게임 방법 이다.예시(deftype VNode1 [tag props])
(defrecord VNode2 [tag props])
(def vnode1
(VNode1. "DIV" {:textContent "Hello world!"}))
;; (->VNode1 "DIV" {:textContent "Hello world!"})
(def vnode2
(VNode2. "DIV" {:textContent "Hello world!"}))
;; (->VNode2 "DIV" {:textContent "Hello world!"})
;; (map->VNode2 {:tag "DIV", :props {:textContent "Hello world!"}})
이렇게 보면 둘 다 별 차이 가 없 는 것 같 지만 사실은 멤버 들 의 조작 에 있어 서 차이 가 있다.
;; deftype
(.-tag vnode1) ;;=> DIV
;; defrecord
(:tag vnode2) ;;=> DIV
;; deftype
(set! (.-tag vnode1) "SPAN")
;; (aset vnode1 "tag" "SPAN")
(.-tag vnode1) ;;=> SPAN
;; defrecord ,
(def vnode3
(assoc vnode2 :tag "SPAN"))
(:tag vnode2) ;;=> DIV
(:tag vnode3) ;;=> SPAN
위 에서 우 리 는
defrecord
정 의 된 데이터 구 조 를 맵 으로 볼 수 있 지만 deftype
은 할 수 없다.* 8195. 그러나 상기 한 것 은 모두 기술 이 고 뒤의 길 은 OOP 에서 우 리 는 두 가지 데이터 모델 을 구축 할 것 이다. 1. 프로 그래 밍 분야 모델;2. 응용 분야 모델.프로 그래 밍 분야 모델 (예 를 들 어 String 등) 에 대해 우 리 는 deftype
로 정의 하여 특수 화 능력 을 제공 할 수 있다.그러나 응용 분야 모델 에 있어 우 리 는 이 를 추상 적 으로 하여 기 존의 도구 (예 를 들 어 assoc
, filter
등) 로 가공 해 야 한다. 또한 응용 분야 모델 에 있어 모든 속성 은 방문 할 수 있 고 개인 적 인 수요 가 존재 하지 않 아야 한다. 모든 속성 이 변 할 수 없 기 때문이다.Protocol
프로 토 콜 은 인터페이스 와 같이 인터페이스 프로 그래 밍 을 실시 할 수 있 습 니 다.위 에서 저 희 는
deftype
과 defrecord
을 통 해 데이터 구 조 를 사용자 정의 할 수 있 습 니 다. 사실은 저 희 는 기 존의 Protocol 이나 사용자 정의 Protocol 을 실현 하여 데이터 구 조 를 확장 하 는 능력 을 가 질 수 있 습 니 다.deftype
와 defrecord
정의 시 Protocol 실현;; protocol IA
(defprotocol IA
(println [this])
(log [this msg]))
;; protocol IB
(defprotocol IB
(print [this]
[this msg]))
;; VNode IA IB
(defrecord VNode [tag props]
IA
(println [this]
(println (:tag this)))
(log [this msg]
(println msg ":" (:tag this)))
IB
(print ([this]
(print (:tag this)))))
;;
(def vnode (VNode. "DIV" {:textContent "Hello!"}))
(println vnode)
(log vnode "Oh-yeah:")
(print vnode)
주의
IB
에서 print 를 Multi - arity method 로 정의 하기 때문에 하나의 함수 서명 만 실현 하 더 라 도 Multi - arity method 방식 으로 이 루어 져 야 합 니 다.(print ([this] (print (:tag this))))
그렇지 않 으 면
java.lang.UnsupportedOperationException: nth not supported on this type: Symbol
의 이상 을 보고 할 것 이다.기 존 데이터 구조 추가 구현 Protocol
Protocol 의 강력 한 점 은 우리 가 실행 할 때 기 존의 데이터 구 조 를 확장 할 수 있 는 행위 이다. 그 중에서
extend-type
특정한 데이터 구 조 를 통 해 여러 개의 Protocol 을 실현 하고 extend-protocol
여러 개의 데이터 구 조 를 통 해 지정 한 Protocol 을 실현 할 수 있다.1. 사용 extend-type
;; js/NodeList, seq
(extend-type js/NodeList
ISeqable
(-seq [this]
(let [l (.-length this)
v (transient [])]
(doseq [i (range l)]
(->> i
(aget this)
(conj! v)))
(persistent! v))))
;;
(map
#(.-textContent %)
(js/document.querySelector "div"))
;; js/RegExp,
(extend-type js/RegExp
IFn
(-invoke ([this s]
(re-matches this s))))
;;
(#"s.*" "some") ;;=> some
2. 사용
extend-protocol
;; js/RegExp js/String,
(extend-protocol IFn
js/RegExp
(-invoke ([this s] (re-matches this s)))
js/String
(-invoke ([this n] (clojure.string/join (take n this)))))
;;
(#"s.*" "some") ;;=> some
("test" 2) ;;=> "te"
또한 저 희 는
satisfies?
을 통 해 특정한 데이터 형식 인 스 턴 스 가 지정 한 Protocol 을 실현 하 는 지 확인 할 수 있 습 니 다.(satisfies? IFn #"test") ;;=> true
;; IFn Ifn?
(Ifn? #"test") ;;=>true
reify
구조 가 지정 한 Protocol 의 무 속성 인 스 턴 스 를 실현 합 니 다.(defn user
[firstname lastname]
(reify
IUser
(full-name [_] (str firstname lastname))))
;;
(def me (user "john" "Huang"))
(full-name me) ;;=> johnHuang
specify
와 specify!
를 사례 로 추가 Protocol 실현specify
가 변 (immutable) 과 복사 가능 (copyable, ICloneable) 의 값 을 추가 로 지정 한 Protocol 을 실현 할 수 있 습 니 다.사실 cljs 값 에 추가 하 는 거 야!(def a "johnHuang")
(def b (specify a
IUser
(full-name [_] "Full Name")))
(full-name a) ;;=>
(full-name b) ;;=>Full Name
specify!
JS 값 추가 지정 프로 토 콜 구현 가능(def a #js {})
(specify! a
IUser
(full-name [_] "Full Name"))
(full-name a) ;;=> "Full Name"
총결산
『 8195 』 cljs 는 데이터 구 조 를 추상 화 하 는 것 을 권장 하기 때문에 List, Map, Set, Vector 외 에 Seq 도 제공 합 니 다.맵, filter, reduce 등 일련의 데이터 조작 함수 가 내장 되 어 있 습 니 다.한편, deftype, defrecord 는 대상 을 대상 으로 프로 그래 밍 을 하거나 내 장 된 조작 이 부족 하여 논 리 를 설명 할 때 확장 하 는 수단 으로 사용 합 니 다.바로
deftype
, defrecord
와 defprotocol
우 리 는 OOP 에서 FP 를 돌 릴 때 더욱 편안 함 을 느 꼈 다. 또한 deftype
, defrecord
와 protocol 세트 는 Expression Problem 을 효과적으로 해결 합 니 다. 구체 적 으로 보 세 요.http://www.ibm.com/developerw... 오리지널 을 존중 합 니 다.http://www.cnblogs.com/fsjohn... ^_^뚱보 존
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
(cljs/run - at (JSVM.: all) "한 번 에 하 얀 DataType, Record, Protocol")프로 토 콜 은 인터페이스 와 같이 인터페이스 프로 그래 밍 을 실시 할 수 있 습 니 다.위 에서 저 희 는 deftype 과 defrecord 을 통 해 데이터 구 조 를 사용자 정의 할 수 있 습 니 다. 사실...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.