iGEL
iGEL

Reputation: 17422

Catch multiple exceptions in Clojure and handle them the same

This is a bit similar to this question, but I want to catch multiple exceptions and handle them all the same. In Ruby, I can write

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

Can I do the same in Clojure? For now I let a function and just call it in each catch body.

Upvotes: 2

Views: 917

Answers (4)

Olim Saidov
Olim Saidov

Reputation: 2844

You can also use this macro:

(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))))

credits https://gist.github.com/Gonzih/5814945

Upvotes: 0

Carcigenicate
Carcigenicate

Reputation: 45836

You could also delegate to a local function, although it gets a little verbose:

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

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

Upvotes: 2

akond
akond

Reputation: 16060

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


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

The slingshot library is available on github.

Upvotes: 8

erdos
erdos

Reputation: 3538

There is no simple built-in solution for that yet, however, there is an open ticket.

You can write a dispatch on type in the catch block by hand.

(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))))

Upvotes: 1

Related Questions