如何让Clojure尊重`* assert *`变量?

时间:2011-02-02 12:35:18

标签: clojure assertions

我理解Clojure的*assert*变量可用于关闭断言,但我做的任何事情似乎都无效。

(defn foo [a]
  {:pre [(pos? a)]}
  (assert (even? a))
  [a])

(binding [*assert* false]
  (foo 1))
!! exception

(binding [*assert* false]
  (foo -2))
!! exception

甚至在定义时绑定false也有同样的问题:

(binding [*assert* false]
  (defn bar [a]
    {:pre [(pos? a)]}
    (assert (even? a))
    [a]))

(bar 1)
!! execption

然后甚至直接设置变量也不起作用。

*assert*
is true

(alter-var-root (var *assert*) not)
*assert*
is still true

(var-set (var *assert*) false)
*assert*
is still true

所以现在我不明白该怎么做。我很困惑。

谢谢。

2 个答案:

答案 0 :(得分:13)

*assert*是编译时变量,而不是运行时变量。它意味着与set!一起用作顶级语句,而不是绑定(当然除非你在绑定中调用eval。)

答案 1 :(得分:4)

断言是以某种方式定义的宏, * assert * 会影响它在扩展时的行为。

如果您尝试使用此代码,它将按预期工作:

(binding [*assert* false]
   (eval '(assert false))
)

以及 var-set 的示例也应该有效:

(var-set (var *assert*) false)
(assert false)