如何有效地捕获不同功能的相同异常?

时间:2014-01-18 07:37:58

标签: exception clojure

以下在REPL中有效,如果数据库关闭,我会收回地图。

(try
 (insert-table "db" "table" {:id 1 :text "text"}) 
 (catch Exception e {:err "can't connect to database"}))

我虽然可以编写一个带有db操作的函数并用(try)包装它。

(defn catch-db-connection-errors
  [db_operation]
  (try
    (db_operation)
    (catch Exception e {:err "can't connect to database"})))

但它没有捕获异常。我可能会忽略一些非常简单的事情......

1 个答案:

答案 0 :(得分:3)

问题在于,在调用函数之前会计算作为参数传递的表单(例如(insert-table "db" "table" {:id 1 :text "text"})),并将结果值传递给函数。要使用其他示例,如果您撰写(println (+ 1 1)),Clojure将首先评估(+ 1 1)以获取2,然后调用(println 2)。因此,如果在您的数据库代码中抛出异常,则在调用catch-db-connection-errors函数之前,因此在try表单之外。

你想要的是一个宏,谢天谢地是Clojure擅长的东西。

(defmacro catch-db-connection-errors [& db-operations]
  `(try
    ~@db-operations
    (catch Exception e {:err "can't connect to database"})))

这允许您传入所需的许多数据库处理表单,并将它们包装在try-catch对中。

(顺便说一句,你可能想要捕捉一些比Exception更具体的东西,否则你最终可能会捕获你不打算做的异常。但当然这不是重点。)