Recide, recidere 의 명령은 2 인칭 단수의 현재 명령을 반환하십시오. 축소합니다
assoc / updatedeferrordeferror-groupgetCurrentSanitizationLevel()createSuppressionMap(...)sanitize(Throwable) , sanitize(Throwable, IPersistentMap)ErrorForm Clojure의 ex-info 매우 유용한 구성입니다. 임의의 데이터의 맵을 예외에 첨부 할 수있어 ex-data 가 발생한 코드를 검사, 로그 또는 다른 방법으로 처리 할 수 있습니다.
예를 들어, assert 진술은 비즈니스 논리에서 귀중한 정신 점검을 제공하지만 실패하면 일반적으로 실패한 방법을 아는 것이 매우 바람직합니다. 이 정보를 예외 문자열에 삽입하려고 시도 할 수 있지만 때로는 관련 데이터가 너무 커서 예외 메시지가 너무 커집니다. 대신 원하는 속성을 확인하고 첨부 된 모든 관련 데이터와 함께 ex-info 던지면 오류 메시지의 간결성을 보존하면서 개발자가 엄청난 시간을 절약 할 수 있습니다.
ex-info 의 주요 약점 중 하나는 사용의 사용이 표준없이 임시 예외를 장려 할 수 있다는 것입니다. Ex-Info를 잡으면 유형이 다른 모든 ex-infos와 동일하며 문자열은 임의적이며 자의적입니다. ex-data 에 나타나는 특정 키를 믿을 수 없으며지도가 완전히 비어있을 가능성이 있습니다.
대규모 프로젝트에서 ex-info 광범위하게 사용하면 이점을 누리고 싶지만 유지하고 싶습니다. 정신의 척도 잘 정의 된 오류의 이점은 응용 프로그램의 각 논리적 구성 요소에서 Universal Clojure 관용구를 깨뜨 리거나 ex-info 사용하는 표준 "던지기 기능"을 정의하는 데 결국 리조트 할 것입니다. ex-info 보장하지만 특정 강성을 보장하십시오 : 아마도 ex-data 문자열에 대한 일반적인 접두사 일 것입니다.
이 라이브러리의 주요 목적 인 Recide는 이 프로세스를 완화 할 수있는 도구를 제공하는 것입니다. 표준 EX-INFO 양식을 정의하기위한 유틸리티와 의도 한대로 사용되는 컴파일 타임을 확인하는 용량을 제공합니다.
recide 의 도구로 생성 된 모든 ex-info 맵에는 두 개의 키가 포함되어 있습니다.
:recide/error , 값은 ErrorForm 의 인스턴스 인 인스턴스입니다.ErrorForm (Recide의 기본값 :recide/type )에 의해 정의 된 "유형 키". Clojure API 문서는 여기에서 찾을 수 있습니다. Java API 문서는 여기에서 찾을 수 있습니다.
recide.core/insist 은 assert 과 유사합니다. 그것의 서명은 동일하며 clojure.core/*assert* 사실 일 때만 실행되는 assert 와 마찬가지로.
그러나 ex-info AssertionError 던지는 대신, "어설 션 실패 : <주장 된 표현 또는 제공된 메시지>". ex-data의 유형은 다음과 같습니다. :recide/assertion . insist 에 의해 사용 된 다른 두 가지 키가 있습니다.
:expression , 값은 insist 에 포함 된 실제 표현:values 값이 실패시 표현식에 사용 된 각 변수의 맵인 맵인 값입니다. :values recide.impl/*capture-insists* 가 참일 때마다 존재하지만 기본적으로 거짓입니다. 라이브러리 로딩 시간에서 다음 중 하나 이상이 사실이면 TRUE로 설정됩니다.
insist 의 서명은 [[expr] [expr message]] 이고, 결과적으로 ex-info의 ex-data는 다음과 같은 형식을 가지고 있습니다.
{ :recide/type :recide/assertion ,
:expression <expr>
:values { ... }}사용 예 :
( let [y not
x true ]
( insist ( y x)))
; ; Unhandled clojure.lang.ExceptionInfo
; ; Assertion failed: (y x)
; ; {:expression (y x),
; ; :values {y #function[clojure.core/not],
; ; x true},
; ; :recide/type :recide/assertion} recide.core/error 에는 두 가지 ([type msg data] [type msg data cause]) 티브가 있습니다. error 맵 data 첨부 된 ex-info 구성하며, 그의 유형 (다시, 기본적으로 :recide/type )이 type 입니다. Java 관용구에 따르면 cause 공급하면 원인을 예외로 만듭니다.
( let [x " not b! haha " ]
( raise :my-type
" my explanation! "
{ :a " a "
:b x}))
; ; #error {
; ; :cause "my explanation!"
; ; :data {:a "a",
; ; :b "not b! haha",
; ; :recide/type :my-type, :recide/error #object[...]}
; ; :via
; ; [{:type clojure.lang.ExceptionInfo
; ; :message "my explanation!"
; ; :data {:a "a",
; ; :b "not b! haha",
; ; :recide/type :my-type, :recide/error #object[...]}
; ; :at [clojure.core$ex_info invokeStatic "core.clj" 4725]}]
; ; :trace ... } recide.core/raise 동일한 두 가지 아티브를 가지고 있습니다. raise error 로 구성된 예외를 던집니다.
assoc / update 편의 기능 : recide.core/assoc-error 및 recide.core/update-error 각각의 ex-data가 assoc 및 update 와 함께 수정 된 원래 유형의 새로운 예외를 반환합니다.
때로는 오류를 예외로 돌리고 던지기 전에 오류의 맵 표현을 통과하고 조작하는 것이 편리 할 수 있습니다. 이를 위해 recide.core/error->map 및 recide.core/error-map->throwable 제공합니다.
또한 맵 양식을 반환하는 오류와 해당 술어 error-map? 대한 대체 error-map "생성자"를 제공합니다. .
메시지 msg , EX-DATA data 및 원인 cause 있는 유형 type 의 오류에 대해서는 지속적인 맵이 다음과 같습니다.
{ :recide/error <ErrorForm>,
:recide/type type,
:recide/msg msg,
:recide/cause cause,
:recide/data data} 다음을 제외한 이러한 모든 키는 :recide/error 제외한 모든 키를 사용자 정의 된 ErrorForm 제공하여 수정할 수 있습니다 (자세한 내용은 아래 참조).
raise 및 error 표준 예외 유형을 제공하는 데 거의 적합하지 않습니다. 이를 더욱 해결하기 위해 Recide는 deferror 및 deferror-group 제공합니다.
deferror deferror 는 오류 이름, 유형 및 "일반적인"문자열을 취하는 매크로입니다. 또한 선택적으로 필요한 키 모음을 취합니다. 필요한 키를 지정하면 소스 코드에 키를 명시 적으로 지정하지 않고 deferror 로 정의 된 도구가 사용될 때마다 컴파일 타임 오류가 발생합니다.
예제 사용 :
( deferror storage-timeout
:storage/timeout
" A storage operation timed out "
[ :method-at-fault :timeout-ms ]) 이 예에서,이 deferror 에 대한이 호출은 두 개의 새로운 매크로 인 storage-timeout 및 raise-storage-timeout 정의합니다. 편의를 위해 유능한 IDE는이 새로운 Vars에 대한 자세한 문서에 액세스 할 수 있습니다.
> ( clojure.repl/doc storage-timeout)
; ; -------------------------
; ; my-ns/storage-timeout
; ; [[detail-str data] [detail-str data cause]]
; ; Macro
; ; Records this raise-site under :storage/timeout in recide, and expands into the equivalent of:
; ;
; ; (ex-info (str "A storage operation timed out: " detail-str)
; ; (assoc data :recide/type :storage/timeout)
; ; cause)
; ;
; ; The following keys are required in the data-map:
; ; #{:method-at-fault,
; ; :timeout-ms}
> ( clojure.repl/doc raise-storage-timeout)
; ; -------------------------
; ; [[detail-str data] [detail-str data cause]]
; ; Macro
; ; Records this raise-site under :storage/timeout in recide, and expands into:
; ;
; ; (raise :storage/timeout
; ; (str "A storage operation timed out: " detail-str)
; ; data
; ; cause)
; ;
; ; The following keys are required in the data-map:
; ; #{:method-at-fault,
; ; :timeout-ms}데이터 맵에서 필요한 각 키를 지정하지 않고이 중 하나를 사용하려고하면 Clojure 컴파일러가 예외를 던집니다.
> ( raise-storage-timeout " blah " { :method-at-fault 'not-really-a-method})
; ; Unhandled clojure.lang.ExceptionInfo
; ; Assertion failed: storage-timeout requires the following missing
; ; keys in its data: :timeout-msdeferror-group deferror-group 온 오류의 가족을 정의하는 매크로입니다. 오류 이름, 기본 유형 선언 및 일부 하위 유형 선언이 필요합니다.
각 기본 유형 선언은 이 오류 그룹의 공통 네임 스페이스를 나타내는 키워드 이거나 첫 번째 요소 가 키워드이고 두 번째 요소가 필요한 키 순서 인 튜플이어야합니다. 여기에 지정된 키는 모든 하위 유형에 필요합니다.
각 하위 유형 선언은 첫 번째 용어가 기호 인 시퀀스로, 두 번째 용어는 오류의 일반적인 문자열이며, 세 번째 (선택 사항) 용어는 해당 하위 유형에 필요한 키 순서입니다.
예:
( deferror-group parse-err
( :query.invalid [ :expression ])
( find-spec " Invalid find spec " )
( inputs " Invalid inputs " [ :invalid ])) 이 예에서는 :query.invalid/find-spec 된 두 :query.invalid/inputs 오류 유형이 있습니다. 첫 번째는 데이터 맵에서 :expression 이지만 두 번째는 :expression 과 :invalid .
deferror 와 마찬가지로 deferror-group 이 생산 한 유틸리티에는 자세한 문서가 있습니다.
> ( clojure.repl/doc parse-err)
; ; -------------------------
; ; recide/parse-err
; ; [[subtype detail-str data] [subtype detail-str data cause]]
; ; Macro
; ; Records this raise-site under :query.invalid/<subtype> in recide, and expands into the
; ; equivalent of:
; ;
; ; (ex-info (str "<subtype-generic-str>: " detail-str)
; ; (assoc data
; ; :recide/type
; ; :query.invalid/<subtype>)
; ; cause)
; ;
; ; The following map shows, for each subtype, what keywords are required in
; ; the data map, and what the generic portion of the string will be:
; ;
; ; {:find-spec {:required #{:expression},
; ; :generic-str "Invalid find spec"},
; ; :inputs {:required #{:expression :invalid},
; ; :generic-str "Invalid inputs"}}
> ( clojure.repl/doc raise-parse-err)
; ; -------------------------
; ; recide/raise-parse-err
; ; [[subtype detail-str data] [subtype detail-str data cause]]
; ; Macro
; ; Records this raise-site under :query.invalid/<subtype> in recide, and expands into:
; ;
; ; (raise :query.invalid/<subtype>
; ; (str "<subtype-generic-str>: " detail-str)
; ; data
; ; cause)
; ;
; ; The following map shows, for each subtype, what keywords are required in
; ; the data map, and what the generic portion of the string will be:
; ;
; ; {:find-spec {:required #{:expression},
; ; :generic-str "Invalid find spec"},
; ; :inputs {:required #{:expression :invalid},
; ; :generic-str "Invalid inputs"}}이전에 볼 수 있듯이 필요한 키는 생략되면 컴파일 타임 오류를 생성합니다.
> ( raise-parse-err :inputs " detailed this, detailed that " { :expression nil })
; ; Unhandled clojure.lang.ExceptionInfo
; ; Assertion failed: parse-err called with subtype :inputs requires
; ; the following missing keys in its data: :invalid 키워드를 사용하여 오류 유형을 지정하는 경우 이러한 키워드를 통해 오류를 catch 수 있습니다. Recide는이 목적을 위해 try* 제공합니다. try* 는 Clojure의 try 로 확장되는 매크로입니다. 이것은 Clojure의 몇 가지 특별한 형태 중 하나입니다. 대부분의 경우 try* 는 try 와 똑같이 행동해야합니다. 강화 된 catch 기능을 노출한다는 점에서 다릅니다. 당신은 잡을 수 있습니다 :
instance? 확인.ErrorForm 에 관계없이)recide.core/try*
[( try* expr* catch-clause* finally-clause?)]
Macro
Expands to Clojure's try Special Form, allowing for enhanced `catch` clauses:
You can catch:
* Classes/Interfaces ( represents an instance? check)
`( catch RuntimeException e ...)`
* keywords ( recide error types ; fully-qualified: :namspace/name, wildcard: :namespace/*)
`( catch :library/error e ...)`
* arbitrary predicates
`( catch bad-error? e ...)`
You can also catch conjunctions/disjunctions of these:
* conjunction
`( catch :and [RuntimeException :library/error bad-error?] e ...)`
* disjunction
`( catch :or [IllegalArgumentException :library/error bad-error?] e ...)`
You can also negate each of these:
`( catch ( :not RuntimeException) e ...)`
`( catch :and [( :not RuntimeException) :library/* ] e ...)`
Otherwise, behavior should match 'normal' catch clauses in `clojure.core/try`. 형식의 키워드 :namespace/* 는 와일드 카드로 사용하여 deferror-group 에 의해 정의 된 것과 같은 Recide 오류 가족을 잡을 수 있습니다.
> ( try* ( raise :genus/species-1
" went extinct "
{ :year -1839421 })
( catch :genus/* e
( println ( :year ( ex-data e)))))
; ; -1839421 Recide는 로그에 안전한 것으로 간주되어야하는 예외의 위생 버전을 획득하는 도구 모음을 제공합니다 (결과적으로 유용하지는 않습니다).
이 클래스에는 소수의 정적 유틸리티 방법이 포함되어 있습니다.
getCurrentSanitizationLevel() Deref'ing recide.sanex/*sanitization-level* 에 해당합니다.
createSuppressionMap(...)부울 args에 해당하는 적절한 키워드로 iPersistentMap을 만듭니다.
sanitize(Throwable) , sanitize(Throwable, IPersistentMap) Clojure ifn recide.sanex/sanitize .
ErrorForm 기본적 으로이 라이브러리가 제기 한 오류는 ex-info 생성자로 사용합니다. recide.utils/serialize-throwable 및 recide.utils/deserialize-throwable (de) 직렬화 및 맵 형식으로 사용합니다 :recide/type , :recide/msg , :recide/data 및 :recide/cause .
새 ErrorForm 정의하면 자신의 라이브러리에 대한 모든 동작을 변경할 수 있습니다. 키워드를 수정하면 라이브러리에서 나오는 "브랜드"오류가 발생할 수 있습니다. 동일한 Arity의 다른 생성자에 대해 ex-info 교체 할 수 있으며, 이는 IExceptionInfo 를 반환 할 것으로 예상됩니다. 예를 들어, Java Interop과 관련된 우려는 새로운 예외 클래스를 만드는 데 동기를 부여 할 수 있지만 Clojure 관용구는 Ex-Info 호환성을 유지하는 데 동기를 부여 할 수 있습니다.
recide.core/def-error-form 으로 사용자 정의를 쉽게 정의 할 수 있으며, 재정의하려는 메소드 만 재정의 할 수 있습니다. 라이브러리 기본값을 반환하기 위해 기본값을 지정하지 않은 메소드.
recide.core 의 오류 처리 방법은 사용 된 특정 ErrorForm 에 비해 적절합니다. 사용자 정의 ErrorForm 사용하여 오류를 만들 려면 recide.core/generate-library! 사용하여 사용자 정의에 맞게 특별히 맞춤화 된 Recide 메서드를 쉽게 생성 할 수 있습니다! .
( ns my-library.error
( :require [recide.core :as rc]))
( rc/def-error-form custom-error-form
( type-kw [_] :my-library/type )
( constructor [_] my-library/error-constructor)
; ; all other methods are filled out with recide defaults.
( def ^:dynamic *capture-insists?* true )
( rc/generate-library! custom-error-form *capture-insists?*)
; ; recide.core/generate-library!
; ; [custom-error capture-flag]
; ; Macro
; ; Generates and defs custom versions of the following recide.core methods, tailored specifically
; ; to custom-error, with variable capture in the generated insist subject to capture-flag.
; ; * error
; ; * error?
; ; * error-map
; ; * error-map?
; ; * throwable->error-map
; ; * raise
; ; * insist
; ; * deferror
; ; * deferror-group
; ;
; ; custom-error should be an instance of recide.error/ErrorForm (see def-error-form).
; ; capture-flag must be resolvable to a dynamic var.