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

Ren*_*rro 1 clojure

我刚刚开始学习 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()?之外,还有其他方法可以从该类中获取特定属性吗?

Sea*_*eld 7

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)