scgilardi.slingshot

https://github.com/scgilardi/slingshot.git

git clone 'https://github.com/scgilardi/slingshot.git'

(ql:quickload :scgilardi.slingshot)
546

Build Status Dependency Status

slingshot

Join the chat at https://gitter.im/scgilardi/slingshot

Enhanced throw and catch for Clojure

Provides try+ and throw+. Each is 100% compatible with Clojure and Java's native try and throw both in source code and at runtime. Each also provides additional capabilities intended to improve ease of use by leveraging Clojure's features like maps, records, and destructuring.

Clojure's native try and throw behave much like those of Java: throw can accept objects derived from java.lang.Throwable and try selects from among catch clauses based on the class of the thrown object.

In addition to fully supporting those uses (whether they originate from Clojure code or from Java code via interop), try+ and throw+ provide these enhanced capabilities:

To throw a non-Throwable object, throw+ wraps it in a Throwable wrapper by calling ex-info. Every instance of IExceptionInfo (whether generated by throw+ or by a direct call to ex-info) is treated as a wrapper.

The wrapper is available via the :wrapper key in &throw-context.

Between being thrown and caught, a wrapper may be further wrapped by other Exceptions (e.g., instances of RuntimeException or java.util.concurrent.ExecutionException). try+ sees through all such wrappers to find the thrown object. The outermost wrapper is available within a catch clause a via the :throwable key in &throw-context.

When throw+ throws a non-Throwable object from within a try+ catch clause, the outermost wrapper of the caught object being processed is captured as the cause of the new throw+. This can be overridden by providing an explicit cause argument to throw+.

Usage

project.clj

Clojars Project

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+))))

Credits

Based on clojure.contrib.condition, data-conveying-exception, discussions on the clojure mailing list and wiki and discussions and implementations by Steve Gilardi, Phil Hagelberg, and Kevin Downey.

License

Copyright © 2011-2014 Stephen C. Gilardi, Kevin Downey, and Phil Hagelberg

Distributed under the Eclipse Public License, the same as Clojure.