web-dev-qa-db-ja.com

Clojureのカスタム例外?

私はClojureでユーザー定義の例外を作成しようとしていて、あらゆる種類の問題を抱えています。ここで概説した方法を試しました。

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

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

しかし、それはClojure 1.2では機能しないようです(または私が何か間違ったことをしています...)。私の環境はClojure1.2、Emacs、そしてleinswankです。

ご協力いただきありがとうございます!

47
erikcw

以下を含むファイルsrc/user/MyException.cljsrcCLASSPATH上にあります)を作成します。

(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>
29
Brian Carper

カスタムクラスを生成するのではなく、カスタム例外を使用する2つのはるかに簡単な方法があります。

  1. 使用 slingshot -これにより、カスタムのthrow+およびcatch+マクロが提供され、任意のオブジェクトと例外をスローおよびキャッチできます。

  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 "???"))))

またはmidjeテストで:

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

FWIW、相互運用上の理由でカスタム例外を作成している場合を除き、代わりにclojure.contrib.conditionの使用を検討することをお勧めします。 APIを使用してカスタムデータをピギーバックするプリコンパイル済みのカスタム例外が付属しています。代わりにそれを使用することで、多くのカスタム例外の作成を回避することができました。ドキュメントはここにあります: http://clojure.github.com/clojure-contrib/condition-api.html

10
Ben Mabey