2011-02-02 23 views
10

我的理解是,Clojure的*assert*變量可以用來關閉斷言,但是我所做的一切似乎都不起作用。如何讓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 

所以現在我不理解的事。我很困惑。

謝謝。

回答

13

*assert*是一個編譯時間變量,不是運行時變量。它意味着與set!一起用作頂級聲明,而不是綁定(當然,除非您在綁定中調用eval)。

4

聲明是以某種方式定義的宏,即* assert *影響它在擴展時的行爲。

,如果你試試這個代碼是否按照預期它會工作:

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

和你的榜樣與VAR設定也應該工作:

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

這是行不通的。您可以通過測試環境變量來動態關閉此功能。 – Virmundi 2016-03-08 04:25:04

相關問題