ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> perl5-porters
perl5-porters
Re: Ignorant wumpus? Or scoping problem?
by Glenn Linderman other posts by this author
Nov 27 2003 12:10AM messages near this date
Re: Ignorant wumpus? Or scoping problem? | Re: Ignorant wumpus? Or scoping problem?
On approximately 11/26/2003 3:03 PM, came the following characters from
the keyboard of Dave Mitchell:
>  On Wed, Nov 26, 2003 at 02:23:35PM -0800, Glenn Linderman wrote:
>  
> >A follow-on question here: when f1 gets its own private reference to $x, 
> >I'm assuming that it would still share the value with any other subs 
> >defined in that block that would also reference $x.  That is, that each 
> >such sub would get its own reference, but only one value would exist, 
> >and the subs could communicate through that variable if they chose to. 
> >Experimentally, this seems to be the case.
>  
>  
>  Each time a block is entered that contains a my declaration, a new instance
>  of that variable is created (in internals terminology, a new SV is
>  created). When subs 'capture' a lexical at compile time, they create a
>  pointer to the current instance. When the block is exited, the block's
>  reference to the instance is deleted, and if nothing else (such as a
>  closure) has a reference to it, it is freed. So this instance may indeed
>  be shared betwen subs, as in 
>  
>      sub new_counter {
>  	my $x = 0;
>  	return sub {$x}, sub {$x++}, sub {$x--};
>      }
>      my ($sub_val, $sub_inc, $sub_dec) = new_counter;

Good.  Thanks for the confirmation on this one too.

> >OK, this warning sure would have been helpful to my understanding this 
> >issue... in fact, why is it only a warning, instead of an error... if 
> >the variable really doesn't exist, and use strict is in effect, should 
> >it not be an error?  Although, I'd rather have it work, as you can read 
> >below....
>  
>  Because it would probably break too much existing code.

Perhaps so, but likely it would only break already broken code, like 
that that I was trying to make work.  In any case, $SIG{__WARN__} lets 
us convert warnings to errors, so ...

> >>The moral of this tale is to be careful with evals. They often do funny
> >>things because the compiler can't know in advance what the eval might
> >>contain.
> >
> >Sure, I understand the compiler can't know in advance what the eval 
> >might contain.... but I guess I would have expected, from comments in 
> >the Camel about eval being evaluated in the lexical context where the 
> >eval call appears, that the variables in the surrounding block would be 
> >available.
> >
> >It seems like it would be possible to make it work that way, and that 
> >working that way would produce more useful results.
>  
>  
>  Consider the following:
>  
>      sub X::DESTROY { print "X::DESTROY called\n" }
>  
>      {
>  	my $x = bless {}, 'X';
>      }
>      print "outside block\n";
>  
>  This outputs
>  
>      X::DESTROY called
>      outside block
>  
>  because $x is destroyed as soon as the block is exited. I hope you'll
>  agree this is the expected behaviour. Now lets modify it a bit:
>  
>      sub X::DESTROY { print "X::DESTROY called\n" }
>  
>      {
>  	my $x = bless {}, 'X';
>          sub f2 { eval 'print "x=$x\n"' }
>      }
>      print "outside block\n";
>      f2;
>  
>  Here f2 and the eval are called after the first and only instance of $x
>  has already been destroyed. What would you like the eval to do at this
>  point?

Well, under the theory that functions containing evals and declared 
within closures should capture all lexicals, $x wouldn't have been 
destroyed yet.  So I guess I'd expect it to do the same thing as the 
case you didn't include, which is:

    sub X::DESTROY { print "X::DESTROY called\n" }
    {
       my $x = bless {}, 'X';
        sub f2 { print "x=$x\n" }
    }
    print "outside block\n";
    f2;

In other words, the fact that the code is eval'd or not eval'd should 
not affect the running of the code.  Of course, this argues that for 
consistency, even functions that only reference one of 500 lexicals in 
the block should preserve all the lexicals, because if any of them were 
recoded to contain an eval, then some of the side-effects of destroying 
the other lexicals could change in timing.  But if you expect the 
lexical to be destroyed, why did you declare it inside the closure?

> >Does anyone think this behavior of Perl/closures/evals is a bug?  One 
> >that is worth fixing?  Or even possible to fix as outlined above?  Or 
> >that will ever get fixed?  Or possibly even documented better, so the 
> >trap can be avoided? 
>  
>  
>  It's not a bug, but it needs to be documented better. I made a start on
>  improving the documentation, but life got in the way.

Yes, well the difference between a bug and a feature is whether they are 
  documented to work that way.  Documentation in this area is very 
sparse, so I guess that means that using it at all is a bug :)

>  [ By the end of today I've got to write a risk assessment and a get-in
>  schedule for a production of Macbeth that I foolishly agreed to get
>  involved in. It's aready 11pm, and I haven't started yet. Instead,
>  I'm engaged in the displacement activity of replying to emails on p5p ;-) ]

A much appreciated displacement activity from my point of view.  This is 
a major project (for me) that is being affected, so I want to understand 
what is what, before getting too far in the wrong direction.

In playing with the Perl debugger some, trying to see what was going on, 
I think I observed that it is also affected by this sort of behavior, or 
  exacerbates this sort of behavior within programs that use evals, by 
adding (I guess) another level of eval somewhere along the line?  I 
usually debug with print statements, so I'm not familiar enough with the 
debugger to be sure of that.  I need to do some more experimentation in 
that area.

>  Another approach is to ensure that the sub that calls the eval
>  mentions all the lexicals that need to be captured and preserved beyond
>  their normal lifespan, eg 
>  
>      {
>  	my ($a,$b,$c);
>  	sub do_eval {
>  	    { no warnings; $a; $b; $c } # capture lexicals
>  	    eval $_[0];
>  	}
>      }
>  
>  I don't know whether this would be practical in your situation though.

Yes, I thought of that, and I also thought of making additional subs as 
accessors for each of the variables in the closure, which would also fix 
the problem, by using the accessor functions in the evals.

These workarounds all seem uglier than preserving all the variables in 
the closure automatically.

-- 
Glenn -- http://nevcal.com/
===========================
Like almost everyone, I receive a lot of spam every day, much of it
offering to help me get out of debt or get rich quick.  It's ridiculous.
-- Bill Gates

And here is why it is ridiculous:
  The division that includes Windows posted an operating profit of $2.26 
  billion on revenue of $2.81 billion.
  --from Reuters via 
http://biz.yahoo.com/rc/031113/tech_microsoft_msn_1.html

So that's profit of over 400% of investment... with a bit more 
investment in Windows technology, particularly in the area of 
reliability, the profit percentage might go down, but so might the bugs 
and security problems?  Seems like it would be a reasonable tradeoff. 
WalMart earnings are 3.4% of investment.
Thread:
Glenn Linderman
Dave Mitchell
Stas Bekman
Brad Baxter
Stas Bekman
Dave Mitchell
Stas Bekman
Glenn Linderman
Dave Mitchell
Glenn Linderman
Dave Mitchell
Glenn Linderman
Brad Baxter
Brad Baxter
Glenn Linderman
Dave Mitchell
Rafael Garcia-Suarez
Glenn Linderman
Stas Bekman
Glenn Linderman
Alan Burlison

Privacy Policy | Email Opt-out | Feedback | Syndication
© 2004 ActiveState, a division of Sophos All rights reserved