我刚刚开始学习 Clojure 并努力提取异常元数据。当我运行这个:
(try
(/ 1 0)
(catch Exception error (println error)))
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,我得到一个 ArithmeticException。打印的堆栈跟踪如下所示:
#error {
:cause Divide by zero
:via
[{:type java.lang.ArithmeticException
:message Divide by zero
:at [clojure.lang.Numbers divide Numbers.java 188]}]
:trace
[[clojure.lang.Numbers divide Numbers.java 188]
[clojure.lang.Numbers divide Numbers.java 3901]
...
]}
Run Code Online (Sandbox Code Playgroud)
它对map我来说看起来像 a ,所以我试图从:causewith 中提取值(:cause error),但它的计算结果为nil。
我怎样才能做到这一点?
挖了一下,我发现这#error {...}是一个java.lang.Throwable类,对吗?
我尝试使用 Java 互操作(.getCause error),但也返回nil. 结果(.getMessage) error)确实返回“除以零”。
除了.getMessage()?之外,还有其他方法可以从该类中获取特定属性吗?
Clojure 必须ex-message从异常中检索消息并ex-cause检索原因——如果有的话。这里的打印显示#error有点误导,因为实际上异常中没有“原因”(在 Java 意义上.getCause),因为没有链式异常。
另一个有用的函数是Throwable->map将异常(所有异常都java.lang.Throwable在其根)转换为常规的 Clojure 哈希映射,您可以在该映射上执行所有常规操作:
user=> (ex-message (try (/ 1 0) (catch Exception e e)))
"Divide by zero"
user=> (keys (Throwable->map (try (/ 1 0) (catch Exception e e))))
(:via :trace :cause)
user=> (:cause (Throwable->map (try (/ 1 0) (catch Exception e e))))
"Divide by zero"
user=>
Run Code Online (Sandbox Code Playgroud)