Пользовательские исключения в Clojure?
Я пытался создать пользовательское исключение в Clojure, и у меня были всевозможные проблемы. Я попробовал метод, изложенный здесь:
http://en.wikibooks.org/wiki/Clojure_Programming/Concepts
(gen-and-load-class 'user.MyException :extends Exception)
Но это не работает в Clojure 1.2 (или я делаю что-то не так...). Моя среда - Clojure 1.2, Emacs и lein swank.
Спасибо за вашу помощь!
3 ответа
Сделать файл src/user/MyException.clj
(где src
находится на CLASSPATH
) содержащий:
(ns user.MyException
(:gen-class :extends java.lang.Exception))
Проверьте значение *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>
Вместо создания пользовательских классов есть два гораздо более простых способа использования пользовательских исключений:
Используйте рогатку - это обеспечивает обычай
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))))
FWIW, если вы не создаете пользовательское исключение по причинам взаимодействия, вы можете рассмотреть возможность использования clojure.contrib.condition
вместо. Он поставляется с предварительно скомпилированным пользовательским исключением, в которое вы добавляете пользовательские данные, используя его API. Я смог избежать создания множества пользовательских исключений, используя его вместо этого. Документы находятся здесь: http://clojure.github.com/clojure-contrib/condition-api.html