【问题标题】:Clojure post-condition fails to execute due to syntax error -- why?Clojure 后置条件由于语法错误而无法执行——为什么?
【发布时间】:2011-10-27 13:42:04
【问题描述】:

在这个函数中:

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

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

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

事实上,这确实可以正常工作。

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

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

【问题讨论】:

  • 请解释一下这个后置条件是什么?我无法弄清楚这个方法的目的是什么。

标签: compilation clojure compiler-errors compiler-warnings post-conditions


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2020-04-21
    • 2022-06-17
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 2019-12-27
    • 1970-01-01
    相关资源
    最近更新 更多