수색…


통사론

  • ::는 네임 스페이스 한정 키워드입니다. 예를 들어 네임 스페이스에 있다면 user :: foo는 user / foo의 줄임말입니다.
  • # : 또는 # - 네임 스페이스별로지도의 키를 한정하기위한 map-literal 구문

비고

Clojure 스펙 은 1.9 버전에서 사용할 수있는 clojure 용 새 사양 / 계약 라이브러리입니다.

사양은 문서, 데이터 유효성 검사, 테스트 용 데이터 생성 등에 포함되는 등 다양한 방식으로 활용됩니다.

술어를 스펙으로 사용

모든 술어 함수를 스펙으로 사용할 수 있습니다. 다음은 간단한 예입니다.

(clojure.spec/valid? odd? 1)
;;=> true

(clojure.spec/valid? odd? 2)
;;=> false

valid? 함수는 spec과 값을 취해 값이 스펙과 일치하면 true를 반환하고 그렇지 않으면 false를 반환합니다.

하나의 다른 흥미로운 술어가 회원으로 설정되었습니다 :

(s/valid? #{:red :green :blue} :red) 
;;=> true

fdef : 함수에 대한 스펙 작성하기

다음 함수가 있다고 가정 해 보겠습니다.

(defn nat-num-count [nums] (count (remove neg? nums)))

같은 이름의 함수 스펙을 정의하여이 함수의 스펙을 작성할 수 있습니다.

(clojure.spec/fdef nat-num-count
        :args (s/cat :nums (s/coll-of number?))
        :ret integer?
        :fn #(<= (:ret %) (-> % :args :nums count)))

:args 는 인수 이름과 해당 스펙에 해당하는 키워드 레이블로 인수 시퀀스를 설명하는 정규식을 사용합니다. spec :args 가 정규 표현식을 요구하는 이유는 함수에 대해 여러 개의 arities를 지원하는 것입니다. :ret 는 함수의 반환 값에 대한 스펙을 지정합니다.

:fn:args:ret 사이의 관계를 제한하는 스펙입니다. test.check를 실행할 때 속성으로 사용됩니다. 이는 하나의 인수, 즉 두 개의 키 : :args (함수에 부합하는 인수)와 :ret (함수의 일치 반환 값)가있는지도로 호출됩니다.

사양 등록

스펙으로 기능하는 술어 외에도 clojure.spec/def 사용하여 스펙을 전체적으로 등록 할 수 있습니다. def 는 등록 된 스펙이 namespace-qualified 키워드에 의해 명명 될 것을 요구합니다.

(clojure.spec/def ::odd-nums odd?)
;;=> :user/odd-nums

(clojure.spec/valid? ::odd-nums 1)
;;=> true
(clojure.spec/valid? ::odd-nums 2)
;;=> false

일단 등록되면 Clojure 프로그램의 어느 곳에서나 스펙을 전역 적으로 참조 할 수 있습니다.

::odd-nums 구문은 user 네임 스페이스에 있다고 가정 할 때 :user/odd-nums 의 줄임말입니다. :: 현재 네임 스페이스 앞에 오는 기호를 한정합니다.

술어를 전달하는 대신 스펙 이름을 valid? 전달할 수 valid? , 그리고 그것은 같은 방식으로 작동합니다.

clojure.spec / 및 & clojure.spec / 또는

clojure.spec/and & clojure.spec/or 여러 사양 또는 조건자를 사용하여보다 복잡한 사양을 만드는 데 사용할 수 있습니다.

(clojure.spec/def ::pos-odd (clojure.spec/and odd? pos?))

(clojure.spec/valid? ::pos-odd 1)
;;=> true

(clojure.spec/valid? ::pos-odd -3)
;;=> false

or 하나 개의 큰 차이와 유사하게 작동합니다. an or spec을 정의 할 때 가능한 각 브랜치에 키워드를 붙여야합니다. 이것은 오류 메시지에서 실패하는 특정 분기를 제공하기 위해 사용됩니다.

(clojure.spec/def ::big-or-small (clojure.spec/or :small #(< % 10) :big #(> % 100)))

(clojure.spec/valid? ::big-or-small 1)
;;=> true

(clojure.spec/valid? ::big-or-small 150)
;;=> true

(clojure.spec/valid? ::big-or-small 20)
;;=> false

or 사용하여 스펙을 준수 할 때 값을 준수하도록 적용 가능한 스펙이 리턴됩니다.

(clojure.spec/conform ::big-or-small 5)
;; => [:small 5]

사양 기록

다음과 같이 레코드를 지정할 수 있습니다.

(clojure.spec/def ::name string?)
(clojure.spec/def ::age pos-int?)
(clojure.spec/def ::occupation string?)

(defrecord Person [name age occupation])

(clojure.spec/def ::person (clojure.spec/keys :req-un [::name ::age ::occupation]))

(clojure.spec/valid? ::person (->Person "john doe" 25 "programmer"))
;;=> true

(clojure.spec/valid? ::person (->Person "john doe" "25" "programmer"))
;;=> false

미래의 어느 시점에서, 레코드의 네임 스페이스에 의해 한정된 레코드 키에 대한 독자 구문 또는 내장 지원이 도입 될 수 있습니다. 이 지원은 이미지도에 존재합니다.

지도 사양

지도에 어떤 키가 있어야하는지 지정하여지도를 지정할 수 있습니다.

(clojure.spec/def ::name string?)
(clojure.spec/def ::age pos-int?)
(clojure.spec/def ::occupation string?)

(clojure.spec/def ::person (clojure.spec/keys :req [::name ::age ::occupation]))

(clojure.spec/valid? ::person {::name "john" ::age 25 ::occupation "programmer"})
;; => true

:req 는 맵에 존재해야하는 키의 벡터입니다. 다음과 같은 추가 옵션을 지정할 수 있습니다 :opt , 선택적 키의 벡터.

지금까지 예제에서는 이름의 키가 네임 스페이스로 한정되어 있어야합니다. 그러나지도 키가 적합하지 않은 것은 일반적입니다. 이 경우 clojure.spec 은 다음을 제공합니다. req와 : opt는 부적합한 키에 해당합니다 : :req-un and :opt-un . 다음은 무 규정 키가있는 동일한 예입니다.

(clojure.spec/def ::name string?)
(clojure.spec/def ::age pos-int?)
(clojure.spec/def ::occupation string?)

(clojure.spec/def ::person (clojure.spec/keys :req-un [::name ::age ::occupation]))

(clojure.spec/valid? ::person {:name "john" :age 25 :occupation "programmer"})
;; => true

:req-un 벡터에서 제공되는 스펙이 여전히 규정 된 방법에 주목하십시오. clojure.spec는 값을 준수 할 때지도에서 규정되지 않은 버전을 자동으로 확인합니다.

네임 스페이스 맵 리터럴 구문을 사용하면 단일 네임 스페이스로 맵의 모든 키를 간략하게 한정 할 수 있습니다. 예 :

(clojure.spec/def ::name string?)
(clojure.spec/def ::age pos-int?)
(clojure.spec/def ::occupation string?)

(clojure.spec/def ::person (clojure.spec/keys :req [::name ::age ::occupation]))

(clojure.spec/valid? ::person #:user{:name "john" :age 25 :occupation "programmer"})
;;=> true

특별한 #: reader 구문을 주목하십시오. 우리는 모든 맵 키를 네임 스페이스로 한정하고자하는 네임 스페이스를 사용합니다. 그러면 제공된 네임 스페이스에 해당하는 사양과 비교하여 확인됩니다.

컬렉션

여러 가지 방법으로 컬렉션을 지정할 수 있습니다. coll-of을 사용하면 콜렉션을 스펙하고 몇 가지 추가 제한 조건을 제공 할 수 있습니다. 다음은 간단한 예입니다.

(clojure.spec/valid? (clojure.spec/coll-of int?) [1 2 3])
;; => true

(clojure.spec/valid? (clojure.spec/coll-of int?) '(1 2 3))
;; => true

제한 조건 옵션은 콜렉션의 주 스펙 / 술어 뒤에옵니다. :kind 과 같이 콜렉션 유형을 제한 할 수 있습니다.

(clojure.spec/valid? (clojure.spec/coll-of int? :kind vector?) [1 2 3])
;; => true

(clojure.spec/valid? (clojure.spec/coll-of int? :kind vector?) '(1 2 3))
;; => false

전달 된 컬렉션이 벡터가 아니기 때문에 위의 내용은 false입니다.

(clojure.spec/valid? (clojure.spec/coll-of int? :kind list?) '(1 2 3))
;; => true

(clojure.spec/valid? (clojure.spec/coll-of int? :kind set?) #{1 2 3})
;; => true

(clojure.spec/valid? (clojure.spec/coll-of int? :kind set?) #{1 "2" 3})
;; => false

집합의 모든 요소가 int가 아니기 때문에 위의 내용은 false입니다.

또한 몇 가지 방법으로 컬렉션의 크기를 제한 할 수 있습니다.

(clojure.spec/valid? (clojure.spec/coll-of int? :kind vector? :count 3) [1 2 3])
;; => true

    (clojure.spec/valid? (clojure.spec/coll-of int? :kind vector? :count 3) [1 2])
;; => false

(clojure.spec/valid? (clojure.spec/coll-of int? :min-count 3 :max-count 5) [1 2 3])
;; => true

    (clojure.spec/valid? (clojure.spec/coll-of int? :min-count 3 :max-count 5) [1 2])
;; => false

다음과 같이 컬렉션의 요소의 고유성을 적용 할 수도 있습니다 :distinct :

(clojure.spec/valid? (clojure.spec/coll-of int? :distinct true) [1 2])
;; => true

(clojure.spec/valid? (clojure.spec/coll-of int? :distinct true) [2 2])
;; => false

coll-of 는 시퀀스의 모든 요소를 ​​검사합니다. 대규모 컬렉션의 경우 이는 매우 비효율적 일 수 있습니다. every 처럼 행동 coll-of 그것은 단지 샘플을 제외하고, 적합성에 대한의 시퀀스 '요소의 상대적으로 작은 수입니다. 이것은 대규모 콜렉션에서 잘 작동합니다. 다음은 그 예입니다.

(clojure.spec/valid? (clojure.spec/every int? :distinct true) [1 2 3 4 5])
;; => true

map-ofcoll-of 와 유사하지만 맵과 유사합니다. 지도에는 키와 값이 모두 있으므로 키의 사양과 값의 사양을 모두 지정해야합니다.

(clojure.spec/valid? (clojure.spec/map-of keyword? string?) {:red "red" :green "green"})
;; => true

coll-of 와 같이 map-of 는 모든 맵 키 / 값의 적합성을 검사합니다. 대형지도의 경우 비효율적입니다. 큰지도에서 비교적 적은 수의 값을 효율적으로 샘플링하기 위해 coll-of , supply map-of every-kv 와 같이 :

(clojure.spec/valid? (clojure.spec/every-kv keyword? string?) {:red "red" :green "green"})
;; => true

시퀀스

spec은 임의의 순서를 기술하고 사용될 수 있습니다. 이것은 많은 정규 표현식 연산을 통해 이것을 지원합니다.

(clojure.spec/valid? (clojure.spec/cat :text string? :int int?) ["test" 1])
;;=> true

cat 에는 시퀀스를 설명하는 데 사용되는 각 사양에 대한 레이블이 필요합니다. cat은 각 요소에 대한 일련의 요소와 스펙을 설명합니다.

alt 는 시퀀스의 주어진 요소에 대해 가능한 많은 사양 중에서 선택하는 데 사용됩니다. 예 :

(clojure.spec/valid? (clojure.spec/cat :text-or-int (clojure.spec/alt :text string? :int int?)) ["test"])
;;=> true

또한 alt 는 각 스펙에 키워드로 레이블을 지정해야합니다.

정규 표현식 시퀀스는 임의적으로 복잡한 시퀀스 표현 스펙을 생성하는 매우 흥미롭고 강력한 방법으로 구성 될 수 있습니다. 다음은 약간 더 복잡한 예제입니다.

(clojure.spec/def ::complex-seq (clojure.spec/+ (clojure.spec/cat :num int? :foo-map (clojure.spec/map-of keyword? int?))))
(clojure.spec/valid? ::complex-seq [0 {:foo 3 :baz 1} 4 {:foo 4}])
;;=> true

여기서 ::complex-seq 는 하나 이상의 요소 쌍의 시퀀스를 검증합니다. 첫 번째 요소는 int이고 두 번째 요소는 키워드의 int 맵입니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow