Comment puis-je lancer une exception dans Clojure?

Je souhaite lancer une exception et avoir ce qui suit:

(throw "Some text")

Cependant, il semble être ignoré.

44
demandé sur dbyrne 2011-03-28 17:44:03

3 réponses

, Vous devez emballer votre chaîne dans un Throwable:

(throw (Throwable. "Some text"))

Ou

(throw (Exception. "Some text"))

Vous pouvez également configurer un bloc try / catch / finally:

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

RÉPLICATION de session:

user=> (myDivision 4 2)
Done.
2
user=> (myDivision 4 0)
Exception message:  Divide by zero
Done.
nil
73
répondu dbyrne 2011-03-28 14:35:24

Clojure.contrib.condition fournit un moyen Clojure-friendly de gérer les exceptions. Vous pouvez soulever des conditions avec des causes. Chaque état peut avoir son propre gestionnaire.

Il y a un certain nombre d'exemples dans la source sur github.

C'est assez flexible, en ce sens que vous pouvez fournir vos propres paires de clés et de valeurs lors de la levée, puis décider quoi faire dans votre gestionnaire en fonction des clés/valeurs.

Par exemple (modifier l'exemple de code):

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

Vous pouvez alors avoir un gestionnaire pour :something-is-wrong:

(handler-case :type
  (do-non-error-condition-stuff)
  (handle :something-is-wrong
    (print-stack-trace *condition*)))
9
répondu edoloughlin 2011-03-29 20:17:23

Si vous voulez lancer une exception et y inclure des informations de débogage (en plus d'une chaîne de message), vous pouvez utiliser la fonction EX-info intégrée.

Pour extraire les données de l'objet ex-info précédemment construit, utilisez ex-data .

Exemple de 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))

Dans un commentaire kolen mentionné slingshot , qui fournit des fonctionnalités avancées qui vous permet non seulement de lancer des objets de type arbitraire (avec throw+), mais aussi utilisez une syntaxe de capture plus flexible pour inspecter les données à l'intérieur des objets jetés (avec try+). Exemples de le repo du projet :

Tenseur / analyse.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+))))
8
répondu dskrvk 2015-06-02 05:59:48