Re: PATCH porting.pod "First Mystery"
Brian McCauley wrote: [...] OK, your last post's examples were more to the point of wanting to destroy objects at the end of the request, and hence here is a new summary: - move the perl4 lib solution to the perl_reference.pod - suggest turning a lexical variable declared with my() into a global variable declared with our() to avoid the closure, with the following "but"s: o if with my() it wasn't crucial to initialize the variables (since my() initialized them to 'undef'), now all variables declared with our() must be explicitly initialized. s/my $counter = 0/our $counter = 0/; [Brian: notice that I prefer *not* to suggest using local() to init vars, and rather have users do that explicitly, which is a good practice] o since the initialization of global variables happens at the beginning of the request, if a variable which contains an object: my $query = CGI->new; is made global: our $query = CGI->new; it won't be destroyed untill the next request. If you wish to make sure that it's destroyed at the end of the request, you must local()'ize the variable: local our $query = CGI->new; - users of perl < 5.6 have to use 'use vars' instead of 'our'. So the above examples become: use vars qw($counter); $counter = 0; and: use vars qw($query); local $query = CGI->new; - point to perl_reference.pod for other workarounds/solutions. Please let me know if I have missed something from your last posts suggestions. __ Stas BekmanJAm_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
Re: PATCH porting.pod "First Mystery"
Stas Bekman <[EMAIL PROTECTED]> writes: > local is perl4-ism, nowadays it's used only for localizing special > perl variables, like $|. Using package variables and local() in to do the job of block-scoped lexicals is a Perl4-ism. On the other hand, when using global variables (in which I include Perl's package variables and Perl's file-scoped lexicals) something with the semantics of local() is useful. It is, therefore, annoying that local cannot be used on lexical variables and even LW has said that this restriction is artifical and wrong. I agree that as a programming technique global variables are vulgar. However the "First Mystery" is all about porting CGI scripts that are already using global variables (implemented using file-scoped lexicals). It is the use of global variables in the first place that is vulgar, using local() does not make the code any more vulgar. > > Secongly it's a smaller change. > > Agreed, but it's not the proper change, your change can break > code. Only in really obscure circumstances. Of course, if at the same time, you make an unrelated change that breaks the code I can see how you'd be tempted to blame me. :-) > Assuming that we had: > > use warnings; > my $counter = 0; > print "hit $counter times"; > > Your change: > > use warnings; > local our $counter; > print "hit $counter times"; No, that's not my change, I said to change "my" to "local our". I didn't say to remove initialization. > > Anyhow, local() does something quite different. It undefines it upon > > exit of the current scope. > > 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. Yes, I know that. > I don't think it has anything to do with finalization, it just looks > like it does. "Bluebells are not blue, they are actually pink and just look like they are blue" :-) I use the term 'finalization' to (amongst other things) refer to declaring an action that is to take place when a given scope is removed from the execution stack. This is what 'local' does. The word, however, is not important as I don't propose to use it in the guide. > 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. The porting guide assumes we start with a working CGI script. If a variable needs to be initialized to a value other than undef then a working script must already do so. > For example we can provide an explicit initialization example The example in my modified porting.pod already shows explicit initialization: local our $counter = 0; > 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. That fails to mention the real reason for using local. > > [ about use vars ] > The guide is written to reduce the number of questions, not raise > their number. Solution: mention both (our and use vars) How about we leave the example as I have it now and say: In this simple example, 'local' is redundant because $counter is explicitly initialized and never holds a reference. For variables that hold references (especially to objects interfacing to entities outside Perl) 'local' ensures timely destruction. For variables lacking explicit initialization 'local' also initializes them to undefined. The 'our' function appeared in 5.6, for backward compatability: use vars qw( $counter ); $counter = 0; We could also go on to talk about the option of explicitly initializing variables with undef() to save the minute overhead of using local() but I think that's unwarranted in porting.pod. Perhaps it should be covered in perl_reference.pod. > > [ file handle example ] > > I didn't suggest that particular use I realise that the simple file handle example was a poor choice to illustrate my point. Here's a better example that could form the basis of a more verbose explation in perl_reference.pod. Suppose you have: my $thing = Thing->new; Now suppose that Thing objects involve lots of resources (shared memory segments, temporary files, large Perl data structures, network connections various database/NNTP/SNPP/whatever servers and so on) and/or suppose that Thing objects perform some sort of output buffering and then flush it in Thing::DESTROY. If I change that to: our $thing = Thing->new; Then all of these resources are held until the script is next run or until the interpreter thread is killed. If I change it to: local our $thing = Thing->new; It does the righ
Re: PATCH porting.pod "First Mystery"
Perrin Harkins wrote: 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. May I also suggest telling users to pass arguments explicitly to subs, instead of doing it implicitly? Nearly all of the Registry-related bugs I see stem from people doing this: my $cgi = CGI->new(); foo() sub foo { $cgi->param(whatever)... } They accidentally create a closure this way and then wonder why their form values never change. Passing $cgi to foo() fixes the problem. We have that already covered in perl_reference.pod, example multirun3.pl. Originally all the workarounds were in the porting.pod but then there were too many of them. so I thought to give just one solution and a pointer to a document/section with the rest of the solutions. If you think it's worth mentioning it in porting.pod in addition to the current place, feel free to adjust it. Your above example prabably more familiar to cgi script writers, than an abstract $counter exapmle. Thanks! __ Stas BekmanJAm_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
Re: PATCH porting.pod "First Mystery"
On Wed, 2003-09-03 at 21:24, Stas Bekman wrote: > [...] > >>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 $|. I agree, using local, and especially "local our" is pretty strange. It may work, but I wouldn't want to encourage people to do that in their code. > 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. May I also suggest telling users to pass arguments explicitly to subs, instead of doing it implicitly? Nearly all of the Registry-related bugs I see stem from people doing this: my $cgi = CGI->new(); foo() sub foo { $cgi->param(whatever)... } They accidentally create a closure this way and then wonder why their form values never change. Passing $cgi to foo() fixes the problem. - Perrin -- Reporting bugs: http://perl.apache.org/bugs/ Mail list info: http://perl.apache.org/maillist/modperl.html
Re: PATCH porting.pod "First Mystery"
[...] 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 consid
Re: PATCH porting.pod "First Mystery"
Stas Bekman <[EMAIL PROTECTED]> writes: > Brian McCauley wrote: > [...] > >>Nice, but: > >> > >> > +The easiest and the fastest way to solve the nested subroutines > >> > +problem is to change C to C C for all variables for > >> > +which you get the warning. The C subroutines are never > >>... > >>[...] > >> > + local our $counter = 0; > >> > >>local our? That should be either local or our, but not both. > > No. > > > >>Do I miss something? > > Yes. (I tried to explain this in Paris but I was in danger of > > causing > > you to miss lunch completely). > > local() and our() do two quite separate and complementary things. > > our() (in effect) declares a lexically scoped alias for a package > > variable. > > local() restores the old value of a package variable (usually undef) > > at the end of the current lexical scope. > > 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. Secongly it's a smaller change. Thirdly you can never be sure the undef would be reached. (I realise after reading the rest of your mail that that statement will not make any sense to you because you've misunderstood what local does and hense where the undef would need to go). > 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. 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. > or if you insist on using both: > > our $counter; > local $counter; # undef $counter Why split them? Doesn't aid readability. Is a pain if the original my() was inside an expression. The comment is confusing. It implies that local performs initialization. It doesn't. It performs finalization. The comment should read: local $counter; # Automatically undef $counter when script terminates > later on I show why this is better for user's understanding. Really? > > The two combined therefore give a package variable two of the most > > useful properties of a lexical one. Of course a real lexical variable > > doesn't really become undefined when it does out of scope - it really > > becomes anonymous, and iff there are no remaining (unweakened) > > references it then gets GCed. But for file-scoped lexicals in the > > main script file the difference is usually not that important. Both > > effectively get killed at the point where global destruction would > > have taken place. > > > >>The rest looks good, but that's not the simplest solution as you have > >>to modify the variables. > > Is there a simpler one? For a typical script with say half a dozen > > variables the "would not remain shared" the "local our" solution > > requires a dozen keystokes on each of half a dozen lines. > > Don't forget that our() is not available before perl 5.6. So we can't > quite eliminate the previous solution unless you suggest to go with a > back-compatible version: > > use vars qw($counter); > local $counter; 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. > and of course the proper solution is: > > use vars qw($counter); > $counter = 0; # or undef No, the proper solution is: local our $counter; 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. 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 :-) ! Mu
Re: PATCH porting.pod "First Mystery"
Brian McCauley wrote: [...] Nice, but: > +The easiest and the fastest way to solve the nested subroutines > +problem is to change C to C C for all variables for > +which you get the warning. The C subroutines are never ... [...] > + local our $counter = 0; local our? That should be either local or our, but not both. No. Do I miss something? Yes. (I tried to explain this in Paris but I was in danger of causing you to miss lunch completely). local() and our() do two quite separate and complementary things. our() (in effect) declares a lexically scoped alias for a package variable. local() restores the old value of a package variable (usually undef) at the end of the current lexical scope. In effect you use local() to undef the variable, instead of explicitly initializing it. Why not doing this explictly? so instead of replacing: my $counter; with: local our $counter; it's probably better to say: our $counter = 0; or if you insist on using both: our $counter; local $counter; # undef $counter later on I show why this is better for user's understanding. The two combined therefore give a package variable two of the most useful properties of a lexical one. Of course a real lexical variable doesn't really become undefined when it does out of scope - it really becomes anonymous, and iff there are no remaining (unweakened) references it then gets GCed. But for file-scoped lexicals in the main script file the difference is usually not that important. Both effectively get killed at the point where global destruction would have taken place. The rest looks good, but that's not the simplest solution as you have to modify the variables. Is there a simpler one? For a typical script with say half a dozen variables the "would not remain shared" the "local our" solution requires a dozen keystokes on each of half a dozen lines. Don't forget that our() is not available before perl 5.6. So we can't quite eliminate the previous solution unless you suggest to go with a back-compatible version: use vars qw($counter); local $counter; and of course the proper solution is: use vars qw($counter); $counter = 0; # or undef which is documented in the perl reference section. Granted, the original "simplest" solution has its troubles. The original "simplest" solution involved finding (and subsequently maintaining) a globally unique filename then splitting the program in to two parts. Thereafer you have to maintain two files even on CGI servers. I would contend that this "simple solution" is not simple. If you are going to all that troble you may as well to the extra 804.65m and produce a proper mod_perl handler and a small wrapper to make it work also in a CGI environment. Also, as of mod_perl2, the "simple solution" is not even, as it stands, a solution as it relied on the script being in the CWD. Remember, we are talking about mp1 guide patching. Not everything that applies to mp1 applies to mp2. e.g., mp2 requires 5.6+, so we indeed can rely on using our() there. And I hope that the problem with CWD will be resolved once Arthur will fix that. If you think that using globals + their initialization is a better solution, which will work well in mp1 and mp2, we can replace the lib.pl solution with it, but should add it to the perl reference section. __ Stas BekmanJAm_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
Re: PATCH porting.pod "First Mystery"
Stas Bekman <[EMAIL PROTECTED]> writes: > [EMAIL PROTECTED] wrote: > > In private mail Stas Bekman <[EMAIL PROTECTED]> writes: > > > >>oops, that should be the modperl list... at modperl-docs we discuss > >>mostly site/docs techical issues and there are very few people on this > >>list to get enough exposure for this kind of feedback request. > > Patch for "The First Mystery" section of the mod_perl porting guide > > as > > per my conversation with Stas at YAPC::Europe::2003. > > Takes out the suggestion of creating a Perl4-style library in the > > same > > directory as a means to port CGI scripts. > > Replaces it with something simpler and more reliable. > > Nice, but: > > > +The easiest and the fastest way to solve the nested subroutines > > +problem is to change C to C C for all variables for > > +which you get the warning. The C subroutines are never > ... > [...] > > + local our $counter = 0; > > local our? That should be either local or our, but not both. No. > Do I miss something? Yes. (I tried to explain this in Paris but I was in danger of causing you to miss lunch completely). local() and our() do two quite separate and complementary things. our() (in effect) declares a lexically scoped alias for a package variable. local() restores the old value of a package variable (usually undef) at the end of the current lexical scope. The two combined therefore give a package variable two of the most useful properties of a lexical one. Of course a real lexical variable doesn't really become undefined when it does out of scope - it really becomes anonymous, and iff there are no remaining (unweakened) references it then gets GCed. But for file-scoped lexicals in the main script file the difference is usually not that important. Both effectively get killed at the point where global destruction would have taken place. > The rest looks good, but that's not the simplest solution as you have > to modify the variables. Is there a simpler one? For a typical script with say half a dozen variables the "would not remain shared" the "local our" solution requires a dozen keystokes on each of half a dozen lines. > Granted, the original "simplest" solution has its troubles. The original "simplest" solution involved finding (and subsequently maintaining) a globally unique filename then splitting the program in to two parts. Thereafer you have to maintain two files even on CGI servers. I would contend that this "simple solution" is not simple. If you are going to all that troble you may as well to the extra 804.65m and produce a proper mod_perl handler and a small wrapper to make it work also in a CGI environment. Also, as of mod_perl2, the "simple solution" is not even, as it stands, a solution as it relied on the script being in the CWD. -- Reporting bugs: http://perl.apache.org/bugs/ Mail list info: http://perl.apache.org/maillist/modperl.html
Re: PATCH porting.pod "First Mystery"
[EMAIL PROTECTED] wrote: In private mail Stas Bekman <[EMAIL PROTECTED]> writes: oops, that should be the modperl list... at modperl-docs we discuss mostly site/docs techical issues and there are very few people on this list to get enough exposure for this kind of feedback request. Patch for "The First Mystery" section of the mod_perl porting guide as per my conversation with Stas at YAPC::Europe::2003. Takes out the suggestion of creating a Perl4-style library in the same directory as a means to port CGI scripts. Replaces it with something simpler and more reliable. Nice, but: > +The easiest and the fastest way to solve the nested subroutines > +problem is to change C to C C for all variables for > +which you get the warning. The C subroutines are never ... [...] > + local our $counter = 0; local our? That should be either local or our, but not both. Do I miss something? The rest looks good, but that's not the simplest solution as you have to modify the variables. Granted, the original "simplest" solution has its troubles. I've also changed "If you put your code into a library or module..." to "If you put all your code into modules..." because if you put your code into a Perl4-style library and then require it in more than one registry script terrible things happen. I don't think this is the place to explain this so I think the guide should just say "modules" and leave it at that. Probably the library problem should be explained elsewhere in the guide. Once this one is sorted out, a patch for perl_reference.pod will follow. Sure, sounds good to me. __ Stas BekmanJAm_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
PATCH porting.pod "First Mystery"
In private mail Stas Bekman <[EMAIL PROTECTED]> writes: > oops, that should be the modperl list... at modperl-docs we discuss > mostly site/docs techical issues and there are very few people on this > list to get enough exposure for this kind of feedback request. Patch for "The First Mystery" section of the mod_perl porting guide as per my conversation with Stas at YAPC::Europe::2003. Takes out the suggestion of creating a Perl4-style library in the same directory as a means to port CGI scripts. Replaces it with something simpler and more reliable. I've also changed "If you put your code into a library or module..." to "If you put all your code into modules..." because if you put your code into a Perl4-style library and then require it in more than one registry script terrible things happen. I don't think this is the place to explain this so I think the guide should just say "modules" and leave it at that. Probably the library problem should be explained elsewhere in the guide. Once this one is sorted out, a patch for perl_reference.pod will follow. --- porting.pod.origThu Aug 14 18:02:27 2003 +++ porting.pod Fri Aug 15 13:37:33 2003 @@ -228,44 +228,42 @@ It's important to understand that the I effect happens only with code that C wraps with a -declaration of the C 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. +declaration of the C subroutine. If you put all your code +into modules, which the main script use()s, this effect doesn't occur. -For example if we move the code from the script into the subroutine -I, place the subroutines into the I 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.) +Do not use simple Perl4-style libraries located in the same directory +as the script. This technique was recommended by a previous version +of this guide but is seriously flawed. Subroutines in such libraries +will only be available to the first script in any given interpreter +thread to require() a library of any given name. This can lead to +strange sporadic failures. It also won't work at all under mod_perl2 +because the current working directory is not the directory containing +the script. + +The easiest and the fastest way to solve the nested subroutines +problem is to change C to C C for all variables for +which you get the warning. The C 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. - mylib.pl: - - - my $counter; - sub run{ -print "Content-type: text/plain\r\n\r\n"; -$counter = 0; -for (1..5) { - increment_counter(); -} + counter.pl: + -- + #!/usr/bin/perl -w + use strict; + + print "Content-type: text/plain\r\n\r\n"; + + local our $counter = 0; + + 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 -- Reporting bugs: http://perl.apache.org/bugs/ Mail list info: http://perl.apache.org/maillist/modperl.html