[...]
In effect you use local() to undef the variable, instead of explicitly
initializing it. Why not doing this explictly?


Firstly it's conceptually neater to use local.  I want to think of the
variable as local rather than as a global variable that needs to be
explicitly reset.

local is perl4-ism, nowadays it's used only for localizing special perl variables, like $|.


Secongly it's a smaller change.

Agreed, but it's not the proper change, your change can break code. Assuming that we had:


use warnings;
my $counter = 0;
print "hit $counter times";

Your change:

use warnings;
local our $counter;
print "hit $counter times";

will generate a warning: Use of uninitialized value in concatenation (.) or string at ...

We have to teach users to initialize globals, not localize them. See more below.

Thirdly you can never be sure the undef would be reached.

And nobody wants it to be reached. The problem is at the beginning of the subsequent request, not at the end of the first request. See more below.


so instead of replacing:

my $counter;

with:

local our $counter;

it's probably better to say:

our $counter = 0;


Surely you meant:

undef our $counter;

Or

our $counter = undef.

No I meant = 0, because that's what the original example does. We try to solve the problem with:


my $counter = 0;

therefore:

our $counter = 0;

does the trick. if you replace

my $counter = 0;

with

local our $counter;

you lose the initialization. This won't work under 'use warnings', which is not clear from the example, but perhaps it should be fixed to do that.

In this case $counter is treated a a number so it's OK to use 0 but
the aim of the game is to come up with a drop-in replacement for all
lexically scoped variables that suffer "will not remain shared".

Anyhow, local() does something quite different.  It undefines it upon
exit of the current scope.  Obviously _most_ of the time it matters
little if the variable is undef on exiting the scope or re-entering it
next time.  But why bother storing up troubles.  Better to do the
right thing from the outset.

I beg your pardon, how did you come up to this conclusion. Point me to the documentation or the source code where this is done. On the exit of the scope local() restores the previous value if any, and if none was assigned in first place (which implies undef) it's reset to undef. I don't think it has anything to do with finalization, it just looks like it does.


Your code:

local our $counter;

is essentially:

our $counter; # undef
{ local $counter; # new undef unrelated to the previous one
$counter = 0; # you missed this, but it's unrelated
}
# $counter == the very first undef here, because it was undef before local was called.


And just to prove you that you aren't so correct with this finalization idea, run the following code:

perl-5.8.1 -lwe 'our $x = 5; { local $x = 6 } print $x'

it prints '5', not undef. so it's *restored* to its previous value not reset to undef. now this:

perl-5.8.1 -lwe 'our $x; { local $x = 6 } print $x'

will indeed restore $x to undef, because that's how it was before local...

However I'm not against your 'local our' solution, I'm just saying that it's less obvious than an explicit initialization, even though it requires more modification. Not-very advanced users will just get confused by this solution. Normally variables need to be initialized before they are used, so they will have to init them in any case and undef is not what they want.

For example we can provide an explicit initialization example and after that suggest that you can say 'local our $foo' to globalize and localize it at the same time if you prefer to init those to undef via local(). Sounds like a good compromise to me.

I thought enough time has gone by that 5.6 can be considered the norm
and the tiny fraction of people doing on-going work on legacy pre-5.6
system should be expected to be familar with the work-rounds required.
On that basis I concuded that the work-rounds needed to get arround
the lack of our() in 5.5 are outside the scope of the the porting
document and belonged in the perl_reference.  In my (as yet
incomplete) revision of the perl_reference document I include mention
of 'use vars'.  If you think this should be in porting I'm not going
to argue.

That's what I suggested, just wasn't clear about it. It should be moved out of porting.pod into perl_reference.pod.


IMNSHO "use vars" is not the proper solution, it is a backward
compatability work-round for people still using old versions of Perl
that prevent them using the proper solution.

Well, what users that do happen to use perl < 5.6 should do? The guide is written to reduce the number of questions, not raise their number. Solution: mention both (our and use vars)


Initialization is not the proper solution.  In some cases, like the
case of the simple counter you can get away with using initialization.
But the proper solution is finalization (using local).  To see why
consider a CGI script that contains, at file scope:

open my $file, '>', $outfile or die "$outfile: $!";

What happens if you change that to:

  use vars qw($file);
  $file = undef;
  open $file, '>', $outfile or die $!;

Well firstly it looks way ugly :-) !

Secondly, it doesn't work under perl < 5.6, so the point is moot if it's made clear ;)


Much more importantly it doesn't
close the file when the script terminates.

I didn't suggest that particular use, however the suggestion in the guide is global and implies that it should work. All I can say here is that closing the file explicitly is a good practice, but otherwise you are right.


open local our $file, '>', $outfile or die $!;

This is a much smaller change to the original script.  It looks much
cleaner.  And most importantly it actually works.

so does:


open our $file, '>', $outfile or die $!;

no? and it works because you don't need to initialize $file

The problem with CWD is not that simple.

The trouble with advising people to create Perl4-style library in the

[...]


But I have already agreed that perl4-style libs solution should be moved to the perl_reference.pod doc... I agree with your arguments.

To summarize:

- move the perl4 lib solution to the perl_reference.pod
- suggest replacing my() with our() to avoid the closure, however this change requires that the variables will be initialized before used in most cases (example of 'open our $foo' which doesn't need to be initialized). you can initialize variables by an explicit assignment of the value, or using the 'local our' trick, which will initialize the variable to under, which is probably not what you want.
- for users of perl < 5.6 suggest to use 'use vars' instead of 'our'.
- point to perl_reference.pod for other workarounds/solutions.


Does it sound good?

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com



--
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html



Reply via email to