ProductPromotion
Logo

Clojure

made by https://0x3d.site

GitHub - scgilardi/slingshot: Enhanced try and throw for Clojure leveraging Clojure's capabilities
Enhanced try and throw for Clojure leveraging Clojure's capabilities - scgilardi/slingshot
Visit Site

GitHub - scgilardi/slingshot: Enhanced try and throw for Clojure leveraging Clojure's capabilities

GitHub - scgilardi/slingshot: Enhanced try and throw for Clojure leveraging Clojure's capabilities

Build Status Dependency Status

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:

  • throw+ can throw any Java object, not just those whose class is derived from java.lang.Throwable.

    Clojure maps or records become an easy way to represent custom exceptions without requiring gen-class.

  • catch clauses within try+ can catch:

    • any Java object thrown by throw+,
    • any map passed to ex-info and thrown by throw or throw+, or
    • any Throwable thrown by Clojure's throw, or Java's throw.

    The first catch clause whose selector matches the thrown object will execute.

    a selector can be:

    • a class name: (e.g., RuntimeException, my.clojure.record), matches any instance of that class, or

    • a key-values vector: (e.g., [key val & kvs]), matches objects where (and (= (get object key) val) ...), or

    • a predicate: (function of one argument like map?, set?), matches any Object for which the predicate returns a truthy value, or

    • a selector form: a form containing one or more instances of % to be replaced by the thrown object, matches any object for which the form evaluates to truthy.

    • the class name, key-values, and predicate selectors are shorthand for these selector forms:

      `<class name>  => (instance? <class name> %)`
      
      `[<key> <val> & <kvs>] => (and (= (get % <key>) <val>) ...)`
      
      `<predicate>   => (<predicate> %)`
      
  • the binding to the caught exception in a catch clause is not required to be a simple symbol. It is subject to destructuring so the body of the catch clause can use the contents of a thrown collection easily.

  • in a catch clause, the context at the throw site is accessible via the hidden argument &throw-context.

  • &throw-context is a map containing:

    for Throwable caught objects:

    :object       the caught object;
    :message      the message, from .getMessage;
    :cause        the cause, from .getCause;
    :stack-trace  the stack trace, from .getStackTrace;
    :throwable    the caught object;
    

    for non-Throwable caught objects (including maps passed to ex-info)

    :object       the caught object;
    :message      the message, from throw+ or ex-info;
    :cause        the cause, from throw+ or ex-info, see below;
    :stack-trace  the stack trace, captured by throw+ or ex-info;
    :wrapper      the Throwable wrapper that carried the object;
    :throwable    the outermost Throwable whose cause chain contains
                  the wrapper, see below.
    

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

  • an optional else clause may appear after all catch clauses and before any finally clause. Its contents will be executed (for side effects) immediately after the code in the try+ body completes only if nothing was thrown.

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.

Status

2019-10-21 Based on a recent request from a slingshot user, I am now working toward a 1.0 release, evaluating and discussing existing issues and PRs. Thank you for the continued interest. I'm particularly happy to see the cljs support and look forward to integrating that.

License

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

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

More Resources
to explore the angular.

mail [email protected] to add your project or resources here 🔥.

Related Articles
to learn about angular.

FAQ's
to learn more about Angular JS.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory