如何从 Clojure 异常中提取元数据?

How to extract metadata from a Clojure Exception?

我刚开始学习 Clojure 并且正在努力提取异常元数据。当我 运行 这个:

(try  
  (/ 1 0)  
  (catch Exception error (println error)))

如预期的那样,我得到了一个 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]
  ...
 ]}

对我来说它看起来像 map,所以我尝试用 (:cause error):cause 中提取值,但它的计算结果为 nil.

我该怎么做?


更新:

深入挖掘后,我发现 #error {...}java.lang.Throwable class,对吗?

我尝试使用 Java 互操作 (.getCause error), but also returns nil. Turns out (.getMessage) error) return“除以零”。

除了 .getMessage() 之外,还有其他方法可以从 class 获取特定属性吗?

Clojure ex-message 从异常中检索消息,ex-cause 检索原因——如果有的话。 #error 的打印显示在这里有点误导,因为异常中实际上没有“原因”(在 .getCause 的 Java 意义上),因为没有链式异常。

另一个有用的函数是 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=>