3

:구문 오류로 인해 Clojure 사후 조건을 실행할 수 없습니다 - 그 이유는 무엇입니까? 이 함수에서

(defn my-post 
    [a] 
    {:post (number? %)} 
    a) 

사후 조건을 실행하지 않는다 (또는 적어도 어설 오류가 발생하지 않는다). 이제는 다음과 같아야한다는 것을 알고 있습니다.

(defn my-post 
    [a] 
    {:post [(number? %)]} ;; note the square brackets around the expression 
    a) 

실제로 제대로 작동합니다.

문제는 이것이 자동으로 실패하고 무엇이 잘못되었는지 파악하는 데 시간이 걸렸습니다. 구문 오류, 런타임 예외는 없습니다.

Clojure가 왜 불평하지 않았는지 이해하기 위해이 코드로 Clojure가하는 것을 이해하고 싶습니다. 매크로 확장? 파괴? 대괄호가 보이지 않으면 코드가 사라지나요? fn위한 조건 맵 (따라서 또한 defn)의 형태이어야한다는

+0

이 게시물 조건이 무엇인가를 설명하세요? 이 방법의 목적이 무엇인지 파악할 수 없습니다. –

답변

5

http://clojure.org/special_forms 문서 :

{:pre [pre-expr*] 
:post [post-expr*]} 

{:post (number? %)}(number? %) 될 것이다는 두 해석 뜻 주장의 순서로 처리되고 별개의 주장 : number?%.

user> (macroexpand-1 '(fn [a] {:post (number? %)} a)) 
(fn* 
([a] 
    (clojure.core/let [% a] 
    (clojure.core/assert number?) 
    (clojure.core/assert %) 
    %))) 

(assert number?) 항상 한 number?이 정의로 통과 핵심 기능되고, 그것은 아마 않는 진정한 가치를 가지고 있습니다. (clojure.core/assert %)%에 true 값이있는 경우 통과합니다. 이는 let을 통해 인수 a의 값에 바인딩되므로 a에 true 값이 있으면 통과합니다. 첫 번째 함수 정의로 (my-post nil)을 호출하면 어설 션이 실패합니다. 제대로 벡터에 후 상태를 넣으면

user> (my-post nil) 
; Evaluation aborted. 
; Assert failed: % 
; [Thrown class java.lang.AssertionError] 

, 그것은 다음과 같이 확장 :

user> (macroexpand-1 '(fn [a] {:post [(number? %)]} a)) 
(fn* 
([a] 
    (clojure.core/let [% a] 
    (clojure.core/assert (number? %)) 
    %)))