Stas Bekman <[EMAIL PROTECTED]> writes: > Brian McCauley wrote: > > Stas Bekman <[EMAIL PROTECTED]> writes: > > > >>- move the perl4 lib solution to the perl_reference.pod > > Will do when I get round to that bit. I still think a mention of it > > is needed in porting.pod to warn people away from it. If you disagree > > simply delete the offending paragraph. > > I'm not disagreeing with you on this. But I will wait for your second > patch and commit both at once otherwise one of the solutions gets > temporary lost...
Yep, OK. > > [...] this is your document so I shall go along with your preferences. > > It's not really mine, I just happen to maintain it. From the previous > discussion it seems that those who cared agreed that it's better to > explicitly declare vars. I assume that was a typo :-) s/declare/initialize/. > Granted 'local our' works, but for (most?) users this point will be > lost, as they will just copy-n-paste examples without understanding > why is it so. Hey, I've conceded. You can stop trying to beat me into submission now. > Power users can figure it out on their own, and I wasn't against > mentioning it at the end after explaining the longer (more > explicit?) solution. I think that makes it a happy compromise, no? I believe that is the compromise embodied in my previous attempt. > > I've tried to keep it brief by moving some of the points (in > > particular 'use vars') into comments inside the code examples where > > they can be expressed more concisely. > > Frankly, I can't understand why do you try to undermine the importance > of always initializing variables. I don't. On the contrary I explain the importance in the narrative and also re-enforce the importance in comments in the example code. I have, at your suggestion, pushed into an afterthought any mention of the fact that if you need to use local() anyhow you can get away without explicit initialization of package variables. Since it appears you _are_ against mentioning it even at the end I'll remove it completely from porting.pod. I don't care, I'm not on a crusade here. > Unless you are an advanced user and know what you are doing, it's a > goodness to always initialize variables before you use them. Of course I agree that initializing variables before you use them is good. It's just that I think that implicit initialization using my() or (if you can't use my(), local()) is better than explicit initialization using undef(). IMNSHO, whenever one sees an explicit ``$var = undef'' or ``undef($var)'' an alarm bell should ring and ones first thought should be "is there a missing/misplaced my()/local()?". BUT.... I can't see why we are still arguing about this. I've worded the document _as_if_ I agreed with you that explicit initialization was a "good thing" per se. The fact that we disagree is, therefore, surely, irrelevant. > > +The easiest and the fastest way to solve the nested subroutines > > +problem is to switch from lexical scope to package scope for all > > +variables for which you get the warning. The C<handler> subroutines > > Would it be better to say: > > The easiest and the fastest way to solve the nested subroutines > problem is to switch every lexically scoped variable you get the > warning for to a global package variable. Yes, that does read more easily. But the dangling "for" now grates. Particularly the juxtaposition "for to". So I'd keep the "for which" even if some people consider such strict English grammar to be affected. I would drop the word "global" since global has many different meanings. By one definition of "global", the orginal file-scoped lexical variable was global. By another definition of "global", package variables (other than ones like %INC) are not global. The use of the phrase "global variable" in Perl documentation as a synonym for "package variable" is AFAIK deprocated. Some people use the phase "global package variable" (or "global global variable" (sic)) to refer to a variable like %INC. I've even seen examples where people use the phrase "global variable" to mean "package variable in package main". > or something like that? OK: The easiest and the fastest way to solve the nested subroutines problem is to switch every lexically scoped variable for which you get the warning to a package variable. > package scope is lexical scope too. Er, now I'm really confused. The our() function declares a lexically scoped alias for a package variable - but this is getting far too subtle. > > +are never called re-entrantly and each resides in a package to itself. > > +Most of the usual disadvantates of package scoped variables are, > > +therefore, not a concern. Note, however, that whereas explicit > > +initialization is often redundant for lexical variables it is usually > > +not redundant for these package variables as they are reused in > > +su bsequent executions of the handler. > > may I suggest the following wording: > > Note, however, that whereas explicit > initialization is not always necessary for lexical variables it is usually > not redundant for these global package variables as they persist in > subsequent executions of the handler and unlike lexical variables, > don't get automatically destroyed at the end of each handler. Again I dislike the word "global" for reasons already stated. I think it would read better if we use consistant terminology. EITHER "not necessary" v "necessary" OR "redundant" v "not redundant" but NOT "not necessary" v "not redundant". I agree that your wording from "as they persist..." is clearer. > > +If the shared variable contains a reference it my hold onto lots of > > shared variable? Can we stick to lexical vs. global, and not confuse > user even further? Er, lexical v _package_ > shared variables are special with ithreads and allow sharing data > across threads. Yes we should loose the word "shared". I had overlooked its special meaning. No need for any adjective here, "the variable" will do just fine. > also s/my/may/ Oops :-) --- porting.pod.orig Fri Oct 10 18:58:48 2003 +++ porting.pod Wed Oct 15 18:50:23 2003 @@ -88,7 +88,7 @@ print "Content-type: text/plain\r\n\r\n"; - my $counter = 0; + my $counter = 0; # Explicit initialization technically redundant for (1..5) { increment_counter(); @@ -195,8 +195,8 @@ print "Content-type: text/plain\r\n\r\n"; - my $counter = 0; - + my $counter = 0; # Explicit initialization technically redundant + for (1..5) { increment_counter(); } @@ -228,51 +228,65 @@ It's important to understand that the I<inner subroutine> effect happens only with code that C<Apache::Registry> wraps with a -declaration of the C<handler> subroutine. If you put your code into a -library or module, which the main script require()'s or use()'s, this -effect doesn't occur. - -For example if we move the code from the script into the subroutine -I<run>, place the subroutines into the I<mylib.pl> file, save it in -the same directory as the script itself and require() it, there will -be no problem at all. (Don't forget the C<1;> at the end of the -library or the require() might fail.) - - mylib.pl: - --------- - my $counter; - sub run{ - print "Content-type: text/plain\r\n\r\n"; - $counter = 0; - for (1..5) { - increment_counter(); - } +declaration of the C<handler> subroutine. If you put all your code +into modules, which the main script C<use()>s, this effect doesn't +occur. + +Do not use Perl4-style libraries. Subroutines in such libraries will +only be available to the first script in any given interpreter thread +to C<require()> a library of any given name. This can lead to +confusing sporadic failures. + +The easiest and the fastest way to solve the nested subroutines +problem is to switch every lexically scoped variable for which you get +the warning to a package variable. The C<handler> subroutines are +never called re-entrantly and each resides in a package to itself. +Most of the usual disadvantates of package scoped variables are, +therefore, not a concern. Note, however, that whereas explicit +initialization is not always necessary for lexical variables it is +usually necessary for these package variables as they persist in +subsequent executions of the handler and unlike lexical variables, +don't get automatically destroyed at the end of each handler. + + + counter.pl: + ---------- + #!/usr/bin/perl -w + use strict; + + print "Content-type: text/plain\r\n\r\n"; + + # In Perl <5.6 our() did not exist, so: + # use vars qw($counter); + our $counter = 0; # Explicit initialization now necessary + + for (1..5) { + increment_counter(); } + sub increment_counter{ $counter++; print "Counter is equal to $counter !\r\n"; } - 1; - - counter.pl: - ---------- - use strict; - require "./mylib.pl"; - run(); -This solution provides the easiest and the fastest way to solve the -nested subroutines problem, since all you have to do is to move the -code into a separate file, by first wrapping the initial code into -some function that you later will call from the script and keeping the -lexically scoped variables that could cause the problem out of this -function. - -But as a general rule of thumb, unless the script is very short, I -tend to write all the code in external libraries, and to have only a -few lines in the main script. Generally the main script simply calls -the main function of my library. Usually I call it C<init()> or -C<run()>. I don't worry about nested subroutine effects anymore -(unless I create them myself :). +If the variable contains a reference it may hold onto lots of +unecessary memory (or worse) if the reference is left to hang about +until the next call to the same handler. For such variables you +should use C<local> so that the value is removed when the C<handler> +subroutine exits. + + my $query = CGI->new; + +becomes: + + local our $query = CGI->new; + +All this is very interesting but as a general rule of thumb, unless +the script is very short, I tend to write all the code in external +libraries, and to have only a few lines in the main script. Generally +the main script simply calls the main function of my library. Usually +I call it C<init()> or C<run()>. I don't worry about nested +subroutine effects anymore (unless I create them myself :). The section 'L<Remedies for Inner Subroutines|general::perl_reference::perl_reference/Remedies_for_Inner_Subroutines>' discusses