Clojure中的自定义异常?

eri*_*kcw 47 exception-handling clojure

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

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

(gen-and-load-class 'user.MyException :extends Exception)
Run Code Online (Sandbox Code Playgroud)

但这似乎不适用于Clojure 1.2(或者我做错了......).我的环境是Clojure 1.2,Emacs和lein swank.

谢谢你的帮助!

Kor*_*rny 70

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

  1. 使用弹弓 - 这提供了自定义throw+catch+宏,可以让你抛出和捕获任何对象,以及异常.

  2. 在clojure 1.4及更高版本中,您可以使用clojure.core/ex-infoclojure.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 "???"))))
Run Code Online (Sandbox Code Playgroud)

或者在midje测试中:

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


Bri*_*per 29

做一个文件src/user/MyException.clj(如果srcCLASSPATH)包含:

(ns user.MyException
  (:gen-class :extends java.lang.Exception))
Run Code Online (Sandbox Code Playgroud)

检查*compile-path*REPL 的值.确保此目录存在且已打开CLASSPATH.如果目录不存在,则创建该目录; Clojure不会为你这样做.

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

编译你的课程:

user> (compile 'user.MyException)
user.MyException
Run Code Online (Sandbox Code Playgroud)

如果它有效,*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
Run Code Online (Sandbox Code Playgroud)

重新启动Clojure REPL/JVM以加载这些类.再次确保这些新类文件已打开CLASSPATH.现在你应该可以使用你的班级了:

user> (user.MyException.)
#<MyException user.MyException>
Run Code Online (Sandbox Code Playgroud)


Ben*_*bey 10

FWIW,除非您为互操作原因创建自定义异常,否则您可能需要考虑使用clojure.contrib.condition.它带有一个预编译的自定义异常,您可以将自定义数据用于使用它的API.我已经能够通过使用它来避免创建许多自定义异常.文档在这里:http: //clojure.github.com/clojure-contrib/condition-api.html

  • `clojure-contrib`现已弃用. (3认同)