Clojure后置条件执行失败,原因是语法错误



在此函数中:

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

后置条件不执行(或者至少不会导致断言错误)。我现在知道它应该是:

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

这实际上是正确的。

问题是这无声地失败了,我花了一段时间才弄清楚出了什么问题。没有语法错误,运行时异常。

我想了解Clojure对这段代码做了什么,以便理解为什么Clojure没有抱怨。宏扩展?解构?如果没有方括号,代码就会消失吗?

http://clojure.org/special_forms说明fn(因此也包括defn)的条件映射格式为:

{: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 %)通过。它通过let绑定到参数a的值,所以如果a有一个真值,它就传递。尝试调用(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? %))
   %)))

相关内容

  • 没有找到相关文章

最新更新