in reply to Re: Where did $@ go?
in thread Where did $@ go?

Tracing back through the calls, I found "Try::Tiny". It claims to localize $@. But if it does funny things, it means the caller must use Try::Tiny as well to get sensible results! Does every try-ing module create a different dependency on its users? That would be a nightmare! I guess it "restores" it after the non-existent catch!

Using Try::Tiny, I get the thrown object in the catch block.

Even data dumper shows, in my original call, $@ to be ''. But the code branch is executed, so it is true.

As for your example, the core docs say that if eval completes without error, then $@ is guaranteed to be a null string, so you can write eval{...}; warn if $@;. You should not need to ensure your block evaluates to true, by original design of the feature.

Replies are listed 'Best First'.
Re^3: Where did $@ go?
by JavaFan (Canon) on Mar 21, 2011 at 10:43 UTC
    As for your example, the core docs say that if eval completes without error, then $@ is guaranteed to be a null string
    Even if that would be true, then
    so you can write eval{...}; warn if $@;
    doesn't follow.

    For the second, you also need $@ to be true if the eval fails. Which doesn't need to be the case.

    The problem is end-of-scope effects. eval { } is a block. Leaving the block, whether due to reaching the end, entering a return, or because the code dies, triggers end of scope effects. Which may cause more code to be executed (think DESTROY blocks). Which may clear, or set $@.

    This is a known, but hard problem to solve (as one doesn't want to lose information carried in $@). There will be improvements in 5.14, IIRC.

      Re even if that were true:
      The eval docs state "If there was no error, $@ is guaranteed to be a null string."

        But that doesn't claim anything for the error situation. For example the following will (at least in Perl 5.12, and earlier versions) wipe $@ even though there is an error:

        sub Eater::DESTROY { eval { 1 }; }; my $ok = eval { my $foo = bless {}, 'Eater'; die "Booo!"; 1; }; warn "OK: [$ok]"; warn "\$\@: [$@]";
        "If there was no error, $@ is guaranteed to be a null string."
        Yeah, but it's useless, because the time frame where $@ is guaranteed to be a null string is less than the width of a semi-colon:

        sub DESTROY {$@ = "Hi"} eval {bless []}; say $@; __END__ Hi!
        No error, but between the finishing of the eval, and the first statement after the eval, the return value of eval is garbage collected, setting $@.