How can I throw an exception in Clojure?

21,560

Solution 1

You need to wrap your string in a Throwable:

(throw (Throwable. "Some text"))

or

(throw (Exception. "Some text"))

You can set up a try/catch/finally block as well:

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

REPL session:

user=> (myDivision 4 2)
Done.
2
user=> (myDivision 4 0)
Exception message:  Divide by zero
Done.
nil

Solution 2

clojure.contrib.condition provides a Clojure-friendly means of handling exceptions. You can raise conditons with causes. Each condition can have its own handler.

There are a number of examples in the source on github.

It's quite flexible, in that you can provide your own key, value pairs when raising and then decide what to do in your handler based on the keys/values.

E.g. (mangling the example code):

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

You can then have a handler for :something-is-wrong:

(handler-case :type
  (do-non-error-condition-stuff)
  (handle :something-is-wrong
    (print-stack-trace *condition*)))

Solution 3

If you want to throw an exception and include some debugging info in it (in addition to a message string), you can use the built-in ex-info function.

To extract the data from the previously-constructed ex-info object, use ex-data.

Example from 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))

In a comment kolen mentioned slingshot, which provides advanced functionality that allows you not only to throw objects of arbitrary type (with throw+), but also use a more flexible catch syntax to inspect data inside thrown objects (with try+). Examples from the project repo:

tensor/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+))))
Share:
21,560
yazz.com
Author by

yazz.com

CEO, Solidity and Web3 developer at https://yazz.com

Updated on July 09, 2022

Comments

  • yazz.com
    yazz.com almost 2 years

    I wish to throw an exception and have the following:

    (throw "Some text")
    

    However it seems to be ignored.

  • Scarlet
    Scarlet almost 11 years
    Now it is replaced with slingshot (taken from Where Did Clojure.Contrib Go)