我一直在尝试在Clojure中创建一个用户定义的异常,并且遇到了各种各样的问题。我尝试了这里概述的方法:
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。
感谢您的帮助!
答案 0 :(得分:69)
使用自定义异常有两种更简单的方法,而不是生成自定义类:
使用slingshot - 这会提供自定义throw+
和catch+
宏,让您可以抛出和捕获任何对象,以及异常。
在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 "???"))))
或者在中间测试中:
(fact "should throw some eels"
(...)
=> (throws clojure.lang.ExceptionInfo
#(= :eels (-> % ex-data :cause))))
答案 1 :(得分:29)
创建一个文件src/user/MyException.clj
(src
所在的文件CLASSPATH
),其中包含:
(ns user.MyException
(:gen-class :extends java.lang.Exception))
检查REPL中*compile-path*
的值。确保此目录存在且位于CLASSPATH
。如果目录不存在,则创建该目录; 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>
答案 2 :(得分:10)
FWIW,除非您因互操作原因而创建自定义异常,否则您可能需要考虑使用clojure.contrib.condition
。它带有一个预编译的自定义异常,您可以将自定义数据用于使用它的API。我已经能够通过使用它来避免创建许多自定义异常。文档在这里:
http://clojure.github.com/clojure-contrib/condition-api.html