On Wed, Aug 06, 2008 at 09:36:16AM -0700, jerry gay wrote:
: i don't think this will work for perl 6. since perl 6 has resumeable
: exceptions (like C<warn>), the meaning of the C<//> operator could be
: ambiguous. given the following statement,
: 
:   my $bill = ack() // thpp() // ppt();
: 
: with perl 6's current semantics, if C<ack()>, throws a resumable
: exception that is handled in the current scope or an outer scope,
: execution will resume before C<//> and the definedness of the result
: from C<ack()> will be tested in order to determine whether or not to
: call C<thpp()>.

Yes, the basic problem with the proposal is that it catches all
exceptions willy nilly and uses them all for control flow whether
that is appropriate or not.  I have some sympathy with the proposal,
however, because I'm currently using exceptions for just that
purpose in the STD grammar.  But it's suffering from the same
difficulty, and I have to be careful to rethrow if the exception
I trapped wasn't the one I expected.

: using your semantics, if a resumable exception is thrown in C<ack()>,
: C<//> will cause C<thpp()> to be invoked immediately, discarding any
: possible defined result from C<ack()>. also, the question arises that
: if C<thpp()> doesn't handle the type of exception thrown, should
: C<ppt()> be called immediately, or only if C<thpp() returns an
: undefined result? seems to me it would try to handle the exception
: thrown by C<ack()>. so how do i signify that my exception has been
: handled, and that i can now assign a default value to C<$bill>?
: 
: in my mind, this strays too far from the meaning of C<//> and adds
: ambiguity that makes the operator unusable. perhaps there's room for
: an operator that gives some sugar for
: 
:   my $bill = try { ack() CATCH { thpp() } };
: 
: but to me that code is concise enough that it doesn't warrant syntactic 
relief.

Well, right now you can write either of:

    my $bill = try { ack() } // thpp();
    my $bill = try { ack() } orelse thpp();

where the latter has the advantage of setting $! on the right to the
return value of the try.  We *could* go as far as making "orelse"
carry try semantics, but I think a more appropriate solution might be
to reduce the precedence of blockless try/do/gather etc. to below
orelse.  And then you could say

    my $bill =
        try ack() orelse
        try thpp() orelse
         do ppt();

But I need to think through the ramifications of such a precedence
change.  It would make blockless "do" rather pointless, for instance,
but maybe that's a worthwhile tradeoff.  And I'm using it above
as a no-op to indicate a "non-try".

It might also be useful to have a try variant that only catches
exceptions intended as benign failure to match.  Or maybe try should
have a way of indicating the severity of exception it wishes to
trap by default.  This could be a keyword variant, or an adverb,
or a pragma.  I'm thinking the pragma is most likely to distribute
syntactic relief nicely over a lexical scope.  In any case it would
only set the default CATCH handler which could still be overridden in
any particular try block.

So, basically, we could just turn blockless try/gather/do into listops
from a precedence point of view, though they'd still essentially be macros.
This seems like a good thing.  At worst it means you need to use parens:

    try($x if $y);

if you need a statement as an argument, where currently you could write

    try $x if $y;

But staring at those two, I'd say the parens are almost a feature from
the least surprise viewpoint.

Larry

Reply via email to