Clojure中的自定义exception?

我一直试图在Clojure中创build一个用户定义的exception,并且遇到各种各样的问题。 我尝试了这里概述的方法:

http://en.wikibooks.org/wiki/Clojure_Programming/Concepts#User-Defined_Exceptions

(gen-and-load-class 'user.MyException :extends Exception) 

但是,这似乎并没有在Clojure 1.2(或我做错了什么…)。 我的环境是Clojure 1.2,Emacs和lein swank。

谢谢你的帮助!

创build一个文件src/user/MyException.clj (其中srcCLASSPATH )包含:

 (ns user.MyException (:gen-class :extends java.lang.Exception)) 

检查REPL处的*compile-path*的值。 确保此目录存在并位于CLASSPATH 。 创build目录,如果它不存在; Clojure不会为你这样做。

 user> *compile-path* "/home/user/foo/target/classes/" user> (System/getProperty "java.class.path") ".......:/home/user/foo/target/classes/:......." 

编译你的类:

 user> (compile 'user.MyException) user.MyException 

如果它工作,在*compile-path*你现在应该有这样的文件:

 /home/user/foo/target/ /home/user/foo/target/classes /home/user/foo/target/classes/user /home/user/foo/target/classes/user/MyException.class /home/user/foo/target/classes/user/MyException__init.class /home/user/foo/target/classes/user/MyException$loading__4410__auto__.class 

重新启动你的Clojure REPL / JVM来加载这些类。 再次确保这些新的类文件位于CLASSPATH 。 现在你应该可以使用你的课堂:

 user> (user.MyException.) #<MyException user.MyException> 

而不是生成自定义类,有两种更简单的方法来使用自定义exception:

  1. 使用弹弓 – 这提供了自定义的throw+catch+macros,让你抛出和捕捉任何对象,以及例外。

  2. 在clojure 1.4及更高版本中,可以使用clojure.core / ex-info和clojure.core / ex-data生成并捕获clojure.lang.ExceptionInfo类,该类包装消息和数据映射。

使用这个很简单:

 (throw (ex-info "My hovercraft is full of eels" {:type :python-exception :cause :eels})) (try (...) (catch clojure.lang.ExceptionInfo e (if (= :eels (-> e ex-data :cause)) (println "beware the shrieking eels!") (println "???")))) 

或者在midjetesting中:

 (fact "should throw some eels" (...) => (throws clojure.lang.ExceptionInfo #(= :eels (-> % ex-data :cause)))) 

FWIW,除非你为互操作的原因创build一个自定义的exception,你可能要考虑使用clojure.contrib.condition 。 它带有一个预编译的自定义exception,可以将自定义数据捎带到使用它的API。 我已经能够避免使用它创build许多自定义exception。 文档在这里: http : //clojure.github.com/clojure-contrib/condition-api.html