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? %))
%)))