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

Reply via email to