Как сделать простой try/catch с помощью clojure?

Ни один из фрагментов кода ниже не работает с clojure 1.6.0

(try
 (prn vv)
  (catch clojure.lang.ExceptionInfo e (prn "catch e: " e))
  (finally (prn "finally") )
)

Я также пробовал это, прочитав здесь несколько других сообщений:

(try
 (doall (prn vv))
  (catch clojure.lang.ExceptionInfo e (prn "catch e: " e))
  (finally (prn "finally") )
)

Что мне не хватает?

Mike

Ответы

Ответ 1

Catching ExceptionInfo поймает только комбайны, созданные с помощью ex-info:

(try
  (throw (ex-info "bad" {:a 1 :b 2}))
  (catch clojure.lang.ExceptionInfo e
    (prn "caught" e)))
;; => "caught" #<ExceptionInfo clojure.lang.ExceptionInfo: bad {:b 2, :a 1}>

Но не другие исключения:

(try
  (/ 1 "0")
  (catch clojure.lang.ExceptionInfo e
    (prn "caught" e)))
;; => ClassCastException java.lang.String cannot be cast to java.lang.Number  clojure.lang.Numbers.divide (Numbers.java:155)

Что вы поймете так:

(try
  (/ 1 "0")
  (catch Exception e
    (prn "caught" e)))
;; => "caught" #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>

Перед оценкой происходят исключения компиляции:

(try
  w is undefined
  (catch Exception e
    (prn "caught" e)))
;; => CompilerException java.lang.RuntimeException: Unable to resolve symbol: w in this context, compiling:(/private/var/folders/8r/y2d3thln6s3fyrl_s6vknb440000gn/T/form-init6601588363347445596.clj:1:5) 

(try
  (eval 'w)
  (catch Exception e
    (prn "caught" e)))
;; => "caught" #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: w in this context, compiling:(/private/var/folders/8r/y2d3thln6s3fyrl_s6vknb440000gn/T/form-init6601588363347445596.clj:1:5)>

Вы также можете иметь несколько команд catch для обработки различных типов исключений.