Front page | perl.perl5.porters |
Postings from March 2008
Re: local $@ has an unwanted side effect
Thread Previous
|
Thread Next
From:
Abigail
Date:
March 21, 2008 10:03
Subject:
Re: local $@ has an unwanted side effect
Message ID:
20080321170345.GC7226@abigail.be
On Fri, Mar 21, 2008 at 06:42:26PM +0200, Yuval Kogman wrote:
> On Fri, Mar 21, 2008 at 17:27:04 +0100, Abigail wrote:
> > On Fri, Mar 21, 2008 at 05:44:33PM +0200, Yuval Kogman wrote:
> > > sub foo {
> > > local $@;
> > >
> > > eval { # a generic wrapper, doesn'tknow about bar()'s details
> > > bar();
> > > };
> > >
> > > if ( $@ ) {
> > > # do something meaningful
> > > die $@;
> > > }
> > > }
> > >
> > > sub bar {
> > > die "blah";
> > > }
> > >
> > > eval { foo() };
> > >
> > > warn "Error: $@";
> > >
> > > in the 'foo' subroutine $@ is localized to prevent clobbering it in
> > > cases such as:
> > >
> > > eval { ... };
> > > foo();
> > > if ( $@ ) { # for the prev eval }
> > >
> > > From a control flow POV everything works correctly here, but in the
> > > outermost eval { } the value of $@ is not preserved (it will jump
> > > though). The value is just ''.
> >
> > Well, that's what you want, isn't? In:
> >
> > eval { ... }
> > foo ();
> > if ($@) { ... }
> >
> > you want $@ to be the result of the first eval {} (at least, that's what
> > I understand from your comment). How else do you want to achieve that then
> > by "ignoring" whatever foo() does with $@?
>
> Umm, that's exactly what foo is trying to achieve with the local, in
> an attempt to not interfere with its caller's environment...
Now, I'm getting confused. To me it seems you are saying that you are
using 'local $@' inside 'foo' as to not clobber an outside $@, and then
you're complaining that $@ isn't set when returning from 'foo'. You can't
have it both ways.
> > Inspecting $@ to check whether an eval die()d is wrong. It can
> > trigger both false positives, and false negatives:
>
> Fair enough, but that goes against the idimatic usage encouraged by
> perlfunc which is widely used today.
>
> > But that's how it ought to be done.
> >
> > While I agree that people might get bitten by 'local $@' (I have myself),
> > it *is* consistent. The eval fails (due to die), which sets $@. Then eval
> > is done, after which the scope is exited, triggering DESTROYs, and unrolling
> > the effects of local. IMO, you are calling for an exception.
>
> Why? The docs doesn't say this. The fact that die actually sets $@
> and not the outer eval { } that does the assignment is not mentioned
> or even hinted at in the docs, and there is little benefit from this
> behavior.
I never claimed that die sets $@. Implementation wise, it might do it (I
have no idea), but from a language point of view, it doesn't. Due to the
die, eval sets $@.
As for the docs, "perldoc -f eval" says:
... If there is a syntax error or runtime error, or a "die" statement
is executed, an undefined value is returned by "eval", and $@ is
set to the error message. ...
Note that the docs do mention the possibility of $@ being something else
than the argument of die(), giving the example of a __DIE__ hook die()ing,
and hence setting $@.
>
> > But that's what local *IS* all about.
>
> ?
>
> > If you don't want the effects of local(), by all means, don't use it.
> > Don't make an exception for a specific case. Specially not for a case
> > where you were using it wrongly in the first place.
>
> Again, there is no evidence to support that my usage was any more
> wrong than the work around is right - I understand how local works,
> and I conjectured that die/eval work independently of it, when it is
> in fact done by actual assignment. That doesn't mean that my usage
> is wrong by design.
>
> --
> Yuval Kogman <nothingmuch@woobling.org>
> http://nothingmuch.woobling.org 0xEBD27418
>
Thread Previous
|
Thread Next