在Clojure中捕获多个异常并对其进行相同处理

时间:2018-07-18 08:43:25

标签: exception clojure exception-handling

这有点类似于this question,但是我想捕获多个异常并全部处理。在Ruby中,我可以写

begin
  rand(2) == 0 ? ([] + '') : (foo)
rescue TypeError, NameError => e
  puts "oops: #{e.message}"
end

我可以在Clojure中做同样的事情吗?现在,我let一个函数,只在每个catch主体中调用它。

4 个答案:

答案 0 :(得分:7)

(ns mastering.stackoverflow
    (:use
        [slingshot.slingshot :only [try+]]))


(try+
    ; ...
    (catch (comp #{TypeError NameError} class) _ "caught"))

The slingshot library在github上可用。

答案 1 :(得分:2)

您还可以委托给局部函数,尽管它有点冗长:

(let [handle #(println %)]
  (try
    (throwing-op)

    (catch TypeError e (handle e))
    (catch NameError e (handle e))))

答案 2 :(得分:1)

目前还没有简单的内置解决方案,但是有open ticket

您可以在catch块中手动键入分派类型。

(try
  (do-dangerous-operation-here)
  (catch Exception e
    (condp (fn [cs t] (some #(instance? % t) cs)) e

      [IllegalStateException IllegalArgumentException]
      (println "Either illegal state or illegal argument!")

      [java.sql.SQLException]
      (println "Sql error!")

      ;; whe pass through the exception when not handled
      (throw e))))

答案 3 :(得分:0)

您也可以使用此宏:

(defmacro try*
  "Macro to catch multiple exceptions with one catch body.
   Usage:
   (try*
     (println :a)
     (println :b)
     (catch* [A B] e (println (class e)))
     (catch C e (println :C))
     (finally (println :finally-clause)))
   Will be expanded to:
   (try
     (println :a)
     (println :b)
     (catch A e (println (class e)))
     (catch B e (println (class e)))
     (catch C e (println :C))
     (finally (println :finally-clause)))
  "
  [& body]
  (letfn [(catch*? [form]
            (and (seq form)
                 (= (first form) 'catch*)))
          (expand [[_catch* classes & catch-tail]]
            (map #(list* 'catch % catch-tail) classes))
          (transform [form]
            (if (catch*? form)
              (expand form)
              [form]))]
    (cons 'try (mapcat transform body))))

积分https://gist.github.com/Gonzih/5814945