50 votes

Des exceptions personnalisées dans Clojure?

J'ai essayé de créer un utilisateur défini par l'exception en Clojure, et ont eu toutes sortes de problèmes. J'ai essayé la méthode décrite ici:

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

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

Mais cela ne semble pas fonctionner en Clojure 1.2 (ou je suis en train de faire quelque chose de mal...). Mon environnement est Clojure 1.2, Emacs, et lein swank.

Merci pour votre aide!

77voto

Korny Points 801

Plutôt que de générer des classes personnalisées, il ya deux beaucoup plus simple des façons d'utiliser des exceptions:

  1. L'utilisation de lance-pierres - cette offre personnalisée throw+ et catch+ des macros qui permettent de lancer et à attraper tous les objets, ainsi que des exceptions.

  2. En clojure 1.4 et au-dessus, vous pouvez utiliser clojure.le noyau de l'ex-info et clojure.le noyau de l'ex-données pour générer et attraper clojure.lang.ExceptionInfo de la classe qui encapsule un message et une carte de données.

L'utilisation est simple:

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

Ou dans un midje test:

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

31voto

Brian Carper Points 40078

Faire un fichier src/user/MyException.clj (où src sur CLASSPATH) contenant:

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

Vérifier la valeur de *compile-path* à la REPL. Assurez-vous que ce répertoire existe et est sur CLASSPATH. Créer le répertoire s'il n'existe pas, Clojure de ne pas le faire pour vous.

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

Compiler votre classe:

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

Si elle a travaillé, en *compile-path* vous devriez maintenant avoir les fichiers quelque chose comme ceci:

/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

Redémarrez votre Clojure REPL / JVM pour charger ces classes. Encore une fois, assurez-vous que ces nouveaux fichiers de classe sont sur CLASSPATH. Maintenant, vous devriez être en mesure d'utiliser votre classe:

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

10voto

Ben Mabey Points 517

FWIW, sauf si vous créez une exception personnalisée pour des raisons d'interopérabilité, vous pouvez envisager d'utiliser plutôt clojure.contrib.condition . Il est livré avec une exception personnalisée précompilée dans laquelle vous attachez des données personnalisées à l'aide de son API. J'ai pu éviter de créer de nombreuses exceptions personnalisées en l'utilisant à la place. Les documents sont ici: http://clojure.github.com/clojure-contrib/condition-api.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X