Stas Bekman <[EMAIL PROTECTED]> writes: > > ... I'd keep the "for which" > > even if some people consider such strict English grammar to be > > affected. > > I guess it reads better if using commas: > > 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.
OK, I still find the strict English grammar easier to read in this instance, but I'll go with your form. > > I would drop the word "global" since global has many different > > meanings. > > Well, the problem I have with this approach is the following: I think > of lexical variables as non-accessible from outside the scope thy > exist in. This is incorrect for variables declared with 'our' and 'use > vars', since those variables are accessible outside the file/package > they were defined in. Which makes them non-lexical. No? I'm sorry I have no idea where that came form. I said: Let's not use the term 'global' to describe a Perl package because it has many meanings to different people. You come back with a discussion of the meaning of lexical scope. > >>package scope is lexical scope too. > > > > Er, now I'm really confused. > > See my comment above. That would be the comment above where you said "package scope is a non-lexical scope" (i.e. the exact opposite)? Anyhow - none of that matters now. > BTW, let's finish off that porting mystery issue when you get a > chance... it's been dragging for too long ;) partially because of me ;) I think porting.pod is done. Now I have to attack perl_reference.pod, and I assume from what you said before you don't want to release the one without the other. --- porting.pod.orig Fri Oct 10 18:58:48 2003 +++ porting.pod Fri Oct 24 13:46:50 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, you get the +warning for, 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