Glenn Linderman wrote:
> 
> Tony Olekshy wrote:
> >
> > Glenn Linderman wrote:
> > >
> > > actually wrapping a bunch of code inside a try block
> > > affects how that code reacts to die, thus affecting the
> > > behavior of the program that previously used die to mean
> > > terminate the program.
> >
> > Hang on, this can't be true. To quote from RFC 88:
> >
> >     try { may_throw_1 }
> >     catch may_throw_2 => { may_throw_3 }
> >     finally { may_throw_4 }
> >
> > is exactly the same as (assuming traditional Perl semantics):
> >
> >     eval { may_throw_1 };
> >     my $exception = $@;
> >     if ($exception) {
> >         my $test = eval { may_throw_2 };
> >         $@ and $exception = $@;
> >         if ( ! $@ and $test ) {
> >             eval { may_throw_3 };
> >             $exception = $@;
> >             }
> >         }
> >     eval { may_throw_4 };
> >     ($exception ||= $@) and die $exception;
> >
> > How can this affect how code reacts to die?  It reacts the same
> > as with eval, whether wrapped in a try or not.  Say I had:
> >
> >         do_something();
> >
> > now I wrap it in a try:
> >
> >         try { do_something(); }
> >
> > this is equivalent to:
> >
> >         eval { do_something(); };
> >         my $exception = $@;
> >         $exception and die $exception;
> >
> > Which is *exactly* the same as bare do_something(); as per Perl 5.
> 
> OK, this example clearly demonstrates something.
> 
> 99% of the catch clauses in the world should be conditional,
> handling only those specific exceptions that it knows about, and
> knows it can handle.  The "catch-all" (unconditional catch of
> anything), is error prone; [...] a "catch-all" might bite off
> _lots_ more than it should chew.  Maybe "catch-all"s that do
> something and then re-throw would be relatively safe.

Yes!

Only when one knows an awful lot about what's going on in the body
of a try is a catch-all that does much more than set a state
variable and re-throw possibly safe, because by definition once an
exception has raised there are a bunch of things one shouldn't make
too many assumptions about.

Here is one possibly safe example:

    try { $y = ( $a * $x * $x + $b * $x + $c ) / $d; }

    catch { $y = undef; }

but this would be even safer:

    try { $y = ( $a * $x * $x + $b * $x + $c ) / $d; }

    catch Exception::CORE::Math => { $y = undef; }

The only case where catch really should be unconditional (and not
just re-throw) is when top-level (some sort of main.pl) code wraps
the whole shebang in a try with this type of explicit purpose:

    try { the_whole_shebang() }

    catch { pass_to_client($@->show(label => 1, trace => 1)) }

Where pass_to_client may be print + exit;

Yours, &c, Tony Olekshy

Reply via email to