On Fri, Jul 29, 2011 at 2:48 AM, Laurent PETIT <laurent.pe...@gmail.com> wrote: > So they decided to go the route of adding a .getSuppressed() (Exceptions) > method in Throwable, thus behaving differently from other finally clauses > ... > > ... so now we have a (with-open) whose semantics are not aligned with those > semantics of Java 7' try-with-resources statement, wrt exception shadowing > from the "finally" block ... :-/
Easily fixed. We already wrap everything in RuntimeException, right? And it's already been suggested elsewhere that we should probably use a specialized subclass, say ClojureRuntimeException. So, just implement ClojureRuntimeException, add some fields and getShadowed and appendShadowed methods to this, and redefine with-open so that it catches any exception, stuffs it into a ClojureRuntimeException as the cause exception if it's not already a ClojureRuntimeException, and now it's holding a ClojureRuntimeException, closes open resources and appends any thrown exceptions to the ClojureRuntimeException's shadowed list. Then throws that. For one resource, something like this should be emitted: (let [x the-resource] (try ... body that works with x ... (catch Throwable t (let [t (if (instance? ClojureRuntimeException t) t (ClojureRuntimeException. (.getMessage t) t))] (try (.close x) (catch Throwable tt (.appendShadowed t tt))) (throw t)))) (.close x)) There's a couple of tiny leaks (.getMessage could throw something, and (ClojureRuntimeException. ...) could throw OOME, plus the infinitesimal chance of a random VMError cropping up) but it looks solid enough for production use and gives Java 7ish semantics. The exception wrapping code elsewhere can do something similar in terms of wrapping in ClojureRuntimeException and only if it's not already wrapped. It'd be nice to be able to differentiate wrapped exceptions from "natural" RuntimeExceptions, and not to have the same one get rewrapped umpteen times so that you have a cause chain of half a dozen RuntimeExceptions before the cause exception. Then we can also have (defn unwrap [x] (if (instance? ClojureRuntimeException x) (recur (.getCause x)) x)) and it will unwrap all Clojure's wrapping, and stop right there even if the exception originally caught and wrapped inside Clojure already had a cause exception. -- Protege: What is this seething mass of parentheses?! Master: Your father's Lisp REPL. This is the language of a true hacker. Not as clumsy or random as C++; a language for a more civilized age. -- 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 Note that posts from new members are moderated - please be patient with your first post. 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