Clojure пост-ўмова не выканаць з-за сінтаксічнай памылкі - чаму?

У гэтай функцыі:

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

Постусловие не выконвае (або, па меншай меры, не выклікае памылку зацвярджэння). Цяпер я ведаю, што гэта павінна было быць:

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

Што робіць, на самай справе, працаваць правільна.

Праблема заключаецца ў тым, што гэта не атрымалася моўчкі, і мне спатрэбілася некаторы час, каб высветліць, што здарылася. Няма сінтаксічных памылак, выключэння падчас выканання.

I would like to understand what Clojure does with this code, in order to understand why Clojure didn't complain. Macro expansions? Destructuring? Does the code just disappear if it doesn't see square braces?

3
Калі ласка, растлумачце, што гэта паведамленне стан? Я не магу зразумець, што гэты метад прызначэння.
дададзена аўтар Abimaran Kugathasan, крыніца

1 адказы

http://clojure.org/special_forms documents that the condition-map for fn (thus also defn) should be of the form:

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

{:post (number? %)} will result in (number? %) being treated as a sequence of assertions, which means it's interpreted as two separate assertions: number? and %.

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

(assert number?) always passes as long as number? is defined and has a true value, which being a core function, it probably does. (clojure.core/assert %) passes if % has a true value. It's bound to the value of your argument a via the let, so it passes if a has a true value. Try calling (my-post nil) with your first function definition and it'll fail the assertion.

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? %))
   %)))
5
дададзена