Nice I will most definitely be checking this out and get back with thoughts. I've been fearing the need to define custom Java Exception for my code and this looks most useful for people who wish to code as much as possible in pure Clojure.
On Fri, Feb 6, 2009 at 9:10 PM, Chouser <chou...@gmail.com> wrote: > > It's not currently possible to define new Java Exceptions without > ahead-of-time compilation, which is sometimes inconvenient. Besides > this, Java's try/catch exception system isn't as flexible as, for > example, Common Lisp's condition/restart system. > > To address both these concerns, I've added a lib called error-kit to > clojure-contrib. Its still pretty experimental, so if you find it > awkward to use of think of better names of the lib itself of anything > it defines, please let me know. Of course I'd also love to hear if > anyone finds it useful. > > Here's a quick demo of its features: > > (require '(clojure.contrib [error-kit :as kit])) > > This defines an error and its action if unhandled. A good choice of > unhandled action is to throw a Java exception so users of your code > who do not want to use error-kit can still use normal Java try/catch > forms to handle the error. The throw-msg macro helps you do this: > > (kit/deferror *number-error* [] [n] > {:msg (str "Number error: " n) > :unhandled (kit/throw-msg NumberFormatException)}) > > This next error derives from the one above, which means if > *odd-number-error* is raised, it can be caught by a handler for > *number-error*: > > (kit/deferror *odd-number-error* [*number-error*] > "Indicates an odd number was given to an operation that is only > defined for even numbers." > [n] > {:msg (str "Can't handle odd number: " n)}) > > Raise an error by name with any extra args as defined by the deferror: > > (defn int-half [i] > (if (even? i) > (quot i 2) > (kit/raise *odd-number-error* i))) > > Since this form ends up calling 'raise', but has no 'with-hander' and > 'handle' form, it will throw a regular Java NumberFormatException: > > (vec (map int-half [2 4 5 8])) > > But you can handle the error, collect details from the args passed to > 'raise', and do whatever you want with it. In this case, just throw > an Exception with a more specific message: > > (kit/with-handler > (vec (map int-half [2 4 5 8])) > (kit/handle *odd-number-error* [n] > (throw (Exception. (format "Odd number %d in vector." n))))) > > The above is equivalent to the more complicated version below: > > (kit/with-handler > (vec (map int-half [2 4 5 8])) > (kit/handle {:keys [n tag]} > (if (isa? tag `*odd-number-error*) > (throw (Exception. (format "Odd number %d in vector." n))) > (kit/do-not-handle)))) > > Returns "invalid" string instead of a vector when an error is > encountered. This is like Clojure's try/catch form. > > (kit/with-handler > (vec (map int-half [2 4 5 8])) > (kit/handle kit/*error* [n] > "invalid")) > > Inserts a zero into the returned vector where there was an error, in > this case [1 2 0 4] > > (kit/with-handler > (vec (map int-half [2 4 5 8])) > (kit/handle *number-error* [n] > (kit/continue-with 0))) > > Here's how to use an intermediate continue, like a CL restart. The > with-handler form below will return [1 2 :oops 5 4] > > (defn int-half-vec [s] > (reduce (fn [v i] > (kit/with-handler > (conj v (int-half i)) > (kit/bind-continue instead-of-half [& instead-seq] > (apply conj v instead-seq)))) > [] s)) > > (kit/with-handler > (int-half-vec [2 4 5 8]) > (kit/handle *number-error* [n] > (kit/continue instead-of-half :oops n))) > > A couple questions, for anyone still reading... > > Should continue-names be namespace qualified, and therefore require > pre-definition in some namespace, like this? > > (kit/defcontinue skip-thing "docstring") > > Could add 'catch' for Java Exceptions and 'finally' support to > with-handler forms. > > --Chouser > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---