2015-09-05 58 views
2

Clojure有可能捕獲編譯時發生的異常嗎?使用的try/catch是好的,易於運行時異常,但假設我有:如何捕獲編譯時異常?

(defmacro will-throw-at-compile [] (assert false "it threw")) 

(try (will-throw-at-compile) (catch Exception e "caught it")) 

我找不到任何辦法趕上這一點,捕捉從未發生過。我也嘗試過不同類型的異常類,似乎不是問題所在。

我也想,既然上面的嘗試是一個運行時調用,使得宏做在編譯時嘗試:

(defmacro t [x] (try x (catch Exception e "caught it"))) 

無法正常工作或:

(t (will-throw-at-compile)) 

也許不能完成?

回答

1

如果宏處理它自己的異常,您可以使其工作。打出來的大多數宏的工作成一個函數:

(defn thrower [] 
    (throw (Exception. "it threw"))) 

(defmacro will-throw 
    [] 
    (try 
    (thrower) 
    (catch Exception e (println "caught it"))) 
    (println "leaving macro")) 

(will-throw) 

在運行這段代碼的結果:

> lein run 
caught it 
leaving macro 

的想法是把大部分或全部的宏功能集成到一個普通函數,因此它可以被稱爲&在編譯時宏機制之外被測試。那麼你可以使用像這樣的常規單元測試:

(deftest t-thrower 
    (is (thrown? Exception (thrower))) 
    (println "t-thrower complete")) 

> lein test 
caught it 
leaving macro 

lein test tst.clj.core 
t-thrower complete 

Ran 1 tests containing 1 assertions. 
0 failures, 0 errors. 
+0

我明白了。我試圖找出一種方法來輕鬆地測試,當它們應該是由宏引發的斷言時,所以我理想情況下不會改變宏本身,而是找到一種方法來檢測它們是否發出異常。我想讓宏實際上拋出斷言,我只是想測試它。 – johnbakers

+3

只需在您的測試中調用macroexpand,而不是評估宏調用。然後它在運行時發生,而這一切都不是問題。 – amalloy

+0

@amalloy感謝的人。試過,工作正常。 – johnbakers