2011/1/25 Shantanu Kumar <kumar.shant...@gmail.com>: > The changed code should catch 'Exception', not 'Throwable' because the > latter is a common ancestor of both 'Exception' and 'Error'. An > 'Error' must not be swallowed at any point in the system, unless you > are writing an app server or a JVM implementation. ;-)
True enough. Does this mean that, with the change from Throwable to Exception, you're ok with the new implementation and it fullfills the expectations of your original email ? > > Regards, > Shantanu > > On Jan 25, 6:11 am, Ken Wesson <kwess...@gmail.com> wrote: >> On Mon, Jan 24, 2011 at 7:43 PM, Laurent PETIT <laurent.pe...@gmail.com> >> wrote: >> > 2011/1/25 Ken Wesson <kwess...@gmail.com>: >> >> Ah, I guess it may be a bit cleaner to just eschew "finally" >> >> altogether and close in the try and in the catch. The one thing that's >> >> a bit icky about that is that if the body close throws, the catch >> >> clause tries to close the stream again. >> >> > argh yes, this may be a problem ... >> >> There's also a bug: _ instead of _# in the close exception discarder. :) >> >> How's about: >> >> (in-ns 'clojure.core) >> (defmacro with-open >> "bindings => [name init ...] >> >> Evaluates body in a try expression with names bound to the values >> of the inits, and a finally clause that calls (.close name) on each >> name in reverse order." >> {:added "1.0"} >> [bindings & body] >> (assert-args with-open >> (vector? bindings) "a vector for its binding" >> (even? (count bindings)) "an even number of forms in binding vector") >> (cond >> (= (count bindings) 0) `(do ~@body) >> (symbol? (bindings 0)) `(let ~(subvec bindings 0 2) >> (let [res# (try >> (with-open ~(subvec >> bindings 2) ~@body) >> (catch Throwable t# >> (try >> (. ~(bindings 0) close) >> (catch Throwable _#)) >> (throw t#)))] >> (. ~(bindings 0) close) >> res#)) >> :else (throw (IllegalArgumentException. >> "with-open only allows Symbols in bindings")))) >> >> No double-closing and no vector. If the body throws, the exception is >> caught, the close is done with any close exception suppressed, and the >> original exception rethrown and that's it. If the body doesn't throw, >> we store it in res and then close. If the close throws here, the >> exception is allowed to propagate. Otherwise we return res. >> >> I've tested this with Foo and it works; modifying Foo to replace the >> close throw with (println "closed"), the doit throw with the integer >> literal 42, or both, I get: >> >> Both throw: >> #<CompilerException java.lang.Exception: doit exception (NO_SOURCE_FILE:46)> >> >> Close throws: >> #<CompilerException java.lang.Exception: close exception (NO_SOURCE_FILE:48)> >> >> Doit throws: >> closed >> #<CompilerException java.lang.Exception: doit exception (NO_SOURCE_FILE:46)> >> >> Neither throws: >> closed >> 42 >> >> The right exception escapes if any exceptions are thrown, and "closed" >> is printed exactly once if close doesn't throw. > > -- > 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 -- 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