develooper 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


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About