in reply to eval: Why use the 'Zombie error' idiom?

Try::Tiny claims that up to 5.14, $@ was cleared at the beginning of the eval { block.

I think that also a destructor containing eval { can clear out $@, so the above idiom is necessary.

Using (for example) Try::Tiny helps avoiding that.

Replies are listed 'Best First'.
Re^2: eval: Why use the 'Zombie error' idiom?
by DouglasDD (Beadle) on Oct 18, 2019 at 09:57 UTC
    ...So, would local-izing $@ be enough to work-around other code's evals messing with our own $@?
    { # scope the `local` local $@; eval { do_something_that_might_die(); 1; } or do { my $error = $@; ## ?? No need for || 'Zombie error' ?? deal_w($error) || die; } }

      The docs for eval suggest this idiom:

      # alter $@ on nefarious repugnancy only { my $e; { local $@; # protect existing $@ eval { test_repugnancy() }; # $@ =~ /nefarious/ and die $@; # Perl 5.14 and higher only $@ =~ /nefarious/ and $e = $@; } die $e if defined $e }

      I don't know - from the discussion in Try::Tiny, it sounds like that, but then, the code of Try::Tiny isn't really that large either. So maybe looking there (or in its test suite) helps find the nasty edge cases.

Re^2: eval: Why use the 'Zombie error' idiom?
by DouglasDD (Beadle) on Oct 18, 2019 at 10:03 UTC
    Forgot to mention that our local coding standards discourage Try::Tiny apparently because it's edge cases have been tripped over in the past.

      Interesting choice. I use Try::Tiny precisely to avoid having to work around the edge cases inherent in eval. YMMV, of course.

        The reason I avoid Try::Tiny is that its catch block is actually a function in disguise, not just a block like with the original eval idiom. So a return from a Try::Tiny catch block returns just from that block, and not from the enclosing function, which is useless and misleading.