Hi, I don't know for sure, but it seems to me that perl 6 way of "writing" exception handling is just a syntactic difference.
For an interesting shift in the possibilities of exception handling/recovery, have a look at how Common Lisp does this with conditions/restart : http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html Which has been ported to clojure by chouser: http://richhickey.github.com/clojure-contrib/error-kit-api.html In a nutshell, with this you can simulate handlers placed higher in the call stack, but those handlers could compute a "recovery value" that would replace the value returned by the innermost from which the exception originated (though this is totally off topic with your original post :-) ). 2010/4/21 ka <sancha...@gmail.com>: > Thanks all for replies. > > Laurent, Alex you guys are right, the problem is only with aesthetics > of nesting / boilerplate. The nesting implementation semantically > expresses exactly what is required. > > The with-cleanup macro seems really neat. Guess I'll learn macros > first and try to implement one. > > One more interesting perspective to exceptional handling is the way > Perl 6 is doing it - http://feather.perl6.nl/syn/S04.html#Exception_handlers > > See this - > > { > my $s = ''; > die 3; > CATCH { > when 1 {$s ~= 'a';} > when 2 {$s ~= 'b';} > when 3 {$s ~= 'c';} > when 4 {$s ~= 'd';} > default {$s ~= 'z';} > } > > is $s, 'c', 'Caught number'; > }; > > Thanks! > > On Apr 21, 7:05 pm, Alex Osborne <a...@meshy.org> wrote: >> ka <sancha...@gmail.com> writes: >> > The whole code gets cluttered with all these try finally (and one >> > catch) statements. >> >> > (try >> > (let [conn1 (API1/getConnection ..)] >> > (try >> > (let [conn2 (API2/getConnection ..)] >> > (try >> > ( ........... Do something with conn1 conn2 ............) >> > (finally >> > (API2/closeConnection conn2)))) >> > (finally >> > (API1/closeConnection conn1)))) >> > (catch Exception ex (.printStackTrace ex))) >> >> I guess the main difference in this compared to your java example is the >> levels of nesting. This may look messy but it's semantically exactly >> what you're trying to express. >> >> > The macro solution looks good. But with 2 different APIs for 2 >> > connections, I would need to write 2 macros right? >> >> > (defmacro with-api1-connection [conn-sym arg1 arg2 & body] >> > `(let [~conn-sym (API1/getConnection ~arg1 ~arg2)] >> > (try >> > ~...@body >> > (finally (API1/closeConnection ~conn-sym))))) >> >> > (defmacro with-api2-connection [conn-sym arg1 arg2 arg3 & body] >> > `(let [~conn-sym (API2/getConnection ~arg1 ~arg2 ~arg3)] >> > (try >> > ~...@body >> > (finally (API2/closeConnection ~conn-sym))))) >> >> You could make things more general: >> >> (with-cleanup [conn1 (API1/getConnection ...) API1/closeConnection >> conn2 (API2/openConnection ...) #(.disconnect %)] >> ...) >> >> I'll leave implementation as an exercise, it's not much more complicated >> than the previous ones, the main trick would just be to make the macro >> recursive, have it expand into: >> >> (let [conn1 (API1/getConnection ...)] >> (try >> (with-cleanup [conn2 (API2/openConnection ...) #(.disconnect %)] >> ...) >> (finally >> (API1/closeConnection conn1)))) >> >> I'd probably start with a signature like this: >> >> (defmacro with-cleanup [[sym create cleanup & more] & body] >> ...) >> >> Take a look at the source for with-open if you get stuck. >> >> >> >> > Coming from Java, this would be implemented as - >> >> > Connection1 conn1 = null; >> > Connection2 conn2 = null; >> > try { >> > conn1 = API1.getConnection ..; >> > conn2 = API2.getConnection ..; >> > ... >> > } >> > catch (){} >> > finally { >> > if (conn1 != null) >> > API1.closeConnection(conn1); >> > if (conn2 != null) >> > API2.closeConnection(conn2); >> > } >> >> > I agree that this code doesn't look good from a purist pov, but any >> > issues besides that? >> >> The problem here is that this breaks lexical scope, conn1 and >> conn2 aren't defined outside their let block. The Java example dodges >> this with mutation. Python/Ruby/JavaScript etc dodge it by having >> special scoping rules: variables are scoped to functions rather than the >> enclosing block. >> >> Clojure's opinion, as I understand it, is that it's not worthwhile >> introducing mutation or special scoping rules simply to avoid some >> nesting, when we have perfectly good tools (macros) for doing purely >> syntactic transformations and removing boilerplate. >> >> There's nothing semantically wrong with nesting, it's just harder >> to read. The Clojure idiom for reducing nesting is usually to use a >> macro like ->, ->> or with-open to flatten it. In this case those >> aren't applicable, so I suggest defining your own. >> >> I'm not sure I phrased that clearly, please let me know if I'm not >> making sense. :-) >> >> Alex >> >> -- >> 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 >> athttp://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 -- 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