2015-09-05 56 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