Как я могу бросить исключение в Clojure? - PullRequest
46 голосов
/ 28 марта 2011

Я хочу выдать исключение и иметь следующее:

(throw "Some text")

Однако оно, похоже, игнорируется.

Ответы [ 3 ]

75 голосов
/ 28 марта 2011

Вам нужно обернуть строку в Throwable :

(throw (Throwable. "Some text"))

или

(throw (Exception. "Some text"))

Вы можете настроить блок try / catch / finally какскважина:

(defn myDivision [x y]
  (try
    (/ x y)
    (catch ArithmeticException e
      (println "Exception message: " (.getMessage e)))
    (finally 
      (println "Done."))))

Сессия REPL:

user=> (myDivision 4 2)
Done.
2
user=> (myDivision 4 0)
Exception message:  Divide by zero
Done.
nil
10 голосов
/ 30 марта 2011

clojure.contrib.condition предоставляет удобный для Clojure способ обработки исключений.Вы можете поднять условия с причинами.Каждое условие может иметь свой собственный обработчик.

Существует несколько примеров в источнике на github .

Это довольно гибкий способ, поскольку вы можете предоставить свой собственный ключ., пары значений при поднятии и затем решите, что делать в вашем обработчике, основываясь на ключах / значениях.

Например (искажение кода примера):

(if (something-wrong x)
  (raise :type :something-is-wrong :arg 'x :value x))

Затем вы можете иметь обработчикдля :something-is-wrong:

(handler-case :type
  (do-non-error-condition-stuff)
  (handle :something-is-wrong
    (print-stack-trace *condition*)))
9 голосов
/ 01 июня 2015

Если вы хотите выдать исключение и включить в него некоторую отладочную информацию (в дополнение к строке сообщения), вы можете использовать встроенную функцию ex-info .

Чтобы извлечь данные из ранее созданного объекта ex-info, используйте ex-data .

Пример из clojuredocs:

(try
  (throw 
    (ex-info "The ice cream has melted!" 
       {:causes             #{:fridge-door-open :dangerously-high-temperature} 
        :current-temperature {:value 25 :unit :celcius}}))
  (catch Exception e (ex-data e))

В комментарии, упомянутом Коленом рогатка , которая предоставляет расширенные функциональные возможности, которые позволяют не только генерировать объекты произвольного типа (с помощью throw +), но и использовать более гибкий синтаксис catch для проверки данных внутри брошенных объектов (с помощью try +).Примеры из репозитория проекта :

тензор / parse.clj

(ns tensor.parse
  (:use [slingshot.slingshot :only [throw+]]))

(defn parse-tree [tree hint]
  (if (bad-tree? tree)
    (throw+ {:type ::bad-tree :tree tree :hint hint})
    (parse-good-tree tree hint)))

math / expression.clj

(ns math.expression
  (:require [tensor.parse]
            [clojure.tools.logging :as log])
  (:use [slingshot.slingshot :only [throw+ try+]]))

(defn read-file [file]
  (try+
    [...]
    (tensor.parse/parse-tree tree)
    [...]
    (catch [:type :tensor.parse/bad-tree] {:keys [tree hint]}
      (log/error "failed to parse tensor" tree "with hint" hint)
      (throw+))
    (catch Object _
      (log/error (:throwable &throw-context) "unexpected error")
      (throw+))))
...