in reply to Question on "Effective Perl Programming"

I personally never test $@ at all. I've seen way too many practical examples of eval failing and yet $@ being left unset so I don't consider using $@ to test whether an eval failed to be wise.

A more robust approach is:

my $okay= eval { ....; 1 }; if( ! $okay ) { warn "Error in eval: $@\n"; }

Here is a quick example of how to make eval fail and leave $@ unset:

sub DESTROY { # local $@; # Uncomment this line to "fix" this eval { # Something that might fail # And failure should just be ignored here }; } my $okay= eval { my $x= bless []; die "The world is coming to an end!!!\n"; 1 }; if( $@ ) { warn "eval failed obviously: $@\n"; } elsif( ! $okay ) { warn "eval failed silently ($@).\n"; } else { warn "eval succeeded.\n"; }

which produces "eval failed silently ()." for me.

I'm a bit disappointed that the authors of "Effective Perl Programming" neglected this technique. You might ask them to have that noted in the errata.

- tye        

Replies are listed 'Best First'.
Re^2: Question on "Effective Perl Programming" (;1 > $@)
by kyle (Abbot) on Sep 06, 2007 at 14:30 UTC

    Ouch! That will eat any useful exception you want to throw too. Consider:

    package EvalEater; sub new { bless {} } sub DESTROY { eval { sleep 1 if 0 } } package main; use Test::More 'tests' => 2; use Exception::Class ( 'Bomb' ); my $okay = eval { my $ee = EvalEater->new(); Bomb->throw( error => 'Ouch!' ); 1; }; ok( ! $@, "Eval appears to succeed: $@" ); ok( ! defined $okay, "Eval failed silently" );

    I see the local $@ will fix the EvalEater, but is there a way to rescue the exception if I can't change EvalEater?

      package DESTROY::EVAL_ERROR::NOT; my %done; sub import { shift @_; for my $pkg ( @_ ) { next if $done{$pkg}++; $pkg .= "::DESTROY"; my $orig= \&{$pkg}; no warnings; *{$pkg}= sub { local $@; $orig->(@_) }; } }

      Then:

      use Broken::Package; use DESTROY::EVAL_ERROR::NOT qw( Broken::Package ); ...

      In other words, "if I can't change EvalEater" need never be true. :)

      - tye        

        If it takes so much to check that an eval worked, maybe something should be fixed?