Пользовательские исключения в Clojure? - PullRequest
47 голосов
/ 01 октября 2010

Я пытался создать пользовательское исключение в 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.

Спасибо за вашу помощь!

Ответы [ 3 ]

69 голосов
/ 23 апреля 2013

Вместо генерации пользовательских классов есть два гораздо более простых способа использования пользовательских исключений:

  1. Использовать рогатка - это предоставляет пользовательские макросы 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 "???"))))

Или в промежуточном тесте:

(fact "should throw some eels"
    (...) 
    => (throws clojure.lang.ExceptionInfo
          #(= :eels (-> % ex-data :cause))))
29 голосов
/ 01 октября 2010

Создайте файл src/user/MyException.clj (где src включен CLASSPATH), содержащий:

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

Проверьте значение *compile-path* в REPL.Убедитесь, что этот каталог существует и находится на 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>
10 голосов
/ 01 октября 2010

FWIW, если вы не создаете пользовательское исключение по причинам взаимодействия, возможно, вы захотите использовать вместо него clojure.contrib.condition.Он поставляется с предварительно скомпилированным пользовательским исключением, в которое вы добавляете пользовательские данные, используя его API.Я смог избежать создания множества пользовательских исключений, используя его вместо этого.Документы здесь: http://clojure.github.com/clojure-contrib/condition-api.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...