> >We write a lot of simple throws, most of which would look
> >like this with the new mechanism as proposed so far:
> >
> > throw Error_DB "ABC.1234: Message about what went wrong.";
> >
> > Without the techniques and hooks I've described in 88v2d2,
> > I'd have to write the following, which has a much lower
> > signal to
> > noise ratio.
> >
> > throw Exception::Error:App:DB tag => "ABC.1234",
> >     message => "Some message about what went wrong.";
> 
> I think your tag/message splitting idea is fragile; what
> happens when some application doesn't want to use tags but
> does want to throw a message like "yikes: buffer overflow"?
>
> Can't heavy users like yourself define some convenience
> function of your own for getting the short version?

The tag/message splitting idea is not a part of RFC 88. It does
*not* happen by default.  However, RFC 88 allows the following,
which is how I would do it.

    package Error::App;  @Error::App::ISA = 'Error';

    sub new
    {
        my ($C, $msg, %opt) = @_;  $C = ref $C || $C;

        my $self = $C->SUPER::new($msg, %opt);

        $self->{message} =~ s/^([A-Z]+\/\d+):\s+//
        and
            $self->{tag} = ref $self .".". $1;

        return bless($self, $C);
        }

The scope of this class is limited to packages that use it,
which presumably want such functionality.  This overriding
mechanism is the "convenience function" we use to get short
versions.  OO serendipity ;-)  I've added this example to
88v2d3.

> > > Hmm... what is the benefit of being able to throw objects
> > > that aren't exceptions?
> >
> >The question is, what happens when someone throws an object
> >that isn't an Exception?
> 
> Run-time error.  Almost certainly they threw the wrong object
> and should find out immediately.

Ok.  I've modified v2d3 to say that die takes a string or an
exception object, and nothing else.  To pass some other object
in an exception, use throw Exception "...", object => $object;

> >Hmm, I'm assuming open throws error exceptions in this
> >example, perhaps I should make that more clear, so I changed
> >the draft to read:
> >
> > if (open(*F, ">foo")) { try { ... } finally { close F; } }
> 
> But everyone will wonder why you aren't trapping the open,
> since it's the most likely statement in there to throw an
> exception and we've been saying all along that it should.  How
> can the reader tell that this open won't throw an exception?

I've changed it to this:

    open(*F, ">foo");  try { ... } finally { close F; }

    If the open raises an exception, it is propagated (for some
    outer try to handle), and the try statement is skipped.

    If foo was opened, try { ... } is attempted, and then F is
    closed whether or not the try block raised an exception.
    Then, if try or close raised an exception, it is propagated
    for some outer try to handle.

    This guarantees that no matter what else happens, if the
    file was opened it is closed.  This sort of functionality
    is commonly required, not just with files and close.

> > > See my earlier comments about all linked blocks sharing
> > > the same lexical scope, btw.
> >
> >I'd rather not introduce that complexity into the RFC.
> 
> It's pretty simple; you're just saying that the blocks share
> the same lexical scope the same way that apparently
> disconnected while and continue blocks do.

Done.

> >  catch Error::DB { ... }
> >
> >     When catch is follwed by a class name, it is syntactic
> >     sugar for:
> >
> >         catch $@->isa($string) { ... }
> >
> >  catch Error::DB, Error:IO { ... }
> >
> >     When catch is follwed by a comma-seperated list of class
> >     names, it is syntactic sugar for:
> >
> >         catch grep { $@->isa($_) } @list { ... }
> 
> There is no difference between these two cases.

Agreed.  I just want to emphasise both forms under DESCRIPTION.
I've changed it to the following.

    catch Error::DB { ... }

        When catch is follwed by a class name, the catch block
        is invoked only if the current error is an instance of
        said class.  It is syntactic sugar for:

            catch $@->isa($string) { ... }

    catch Error::DB, Error:IO { ... }

        When catch is follwed by a comma-seperated list of class
        names, the catch block is invoked only if the current is
        an instance of one of the given classes.  It is
        syntactic sugar for:

            catch grep { $@->isa($_) } @list { ... }

Yours, &c, Tony Olekshy

Reply via email to