Stas Bekman <[EMAIL PROTECTED]> writes:

> Brian McCauley wrote:
> 
> > I think porting.pod is done.
> 
> Indeed.
> 
> > 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.
> 
> Yes. Let's commit them together.

Here's a _very_ rough first cut at perl_reference.pod.  I haven't even
proof-read it yet so it's probably got spelling a and grammar errors
but I just want to be sure I'm going in the right direction.

--- perl_reference.pod.orig     Thu Aug 14 18:11:11 2003
+++ perl_reference.pod  Fri Oct 31 19:46:56 2003
@@ -863,16 +863,17 @@
 problem, Perl will always alert you.
 
 Given that you have a script that has this problem, what are the ways
-to solve it? There are many of them and we will discuss some of them
-here.
+to solve it? There have been many of them suggested in the past and we
+will discuss some of them here.
 
 We will use the following code to show the different solutions.
 
   multirun.pl
   -----------
-  #!/usr/bin/perl -w
+  #!/usr/bin/perl
   
   use strict;
+  use warnings;
   
   for (1..3){
     print "run: [time $_]\n";
@@ -925,20 +926,26 @@
   Counter is equal to 5 !
   Counter is equal to 6 !
 
-Obviously, the C<$counter> variable is not reinitialized on each
-execution of run(). It retains its value from the previous execution,
-and sub increment_counter() increments that.
-
-One of the workarounds is to use globally declared variables, with the
-C<vars> pragma.
+Apparently, the C<$counter> variable is not reinitialized on each
+execution of run(), it retains its value from the previous execution,
+and increment_counter() increments that.  Actually that's not quite
+what happens.  On each execution of run() a new C<$counter> variable
+is initialized to zero but increment_counter is remains bound to the
+C<$counter> variable from the first call to run().
+
+The simplest of the workarounds is to use package-scoped variables,
+declared using C<our> or, on older versions of Perl, the C<vars>
+pragma.  Note that whereas using C<my> declaration also implicitly
+initializes variables to undefined the C<our> declaration does not,
+and so you may need to add explicit initialisation.
 
   multirun1.pl
-  -----------
-  #!/usr/bin/perl -w
+  ------------
+  #!/usr/bin/perl
   
   use strict;
-  use vars qw($counter);
-  
+  use warnings;  
+
   for (1..3){
     print "run: [time $_]\n";
     run();
@@ -946,7 +953,7 @@
   
   sub run {
   
-    $counter = 0;
+    our $counter = 0;
   
     increment_counter();
     increment_counter();
@@ -977,11 +984,34 @@
 problem, since there is no C<my()> (lexically defined) variable used
 in the nested subroutine.
 
-Another approach is to use fully qualified variables. This is better,
-since less memory will be used, but it adds a typing overhead:
+In the above example we know C<$counter> is just a simple small
+scalar.  In the general case variables could reference external
+resource handles or large data structures.  In that situation the fact
+that the variable would not be released immediately when run()
+completes could be a problem.  To avoid this you should put C<local>
+in front of all you C<our> declarations for all variables other than
+simple scalars.  This has the effect of restoring the variable to its
+previous value (usually undefined) upon exit from the current scope.
+As a side-effect C<local> also initializes the variables to C<undef>.
+So, you recall that thing I said about needing to remeber to add
+explicit initialization when you replace C<my> by C<our>, well you can
+forget it again if you replace C<my> with C<local our>.
+
+Be warned that C<local> will not release circular data structures and
+if the original CGI script relied on process termination to clean up
+after it then it will leak memory as a registry script.
+
+A varient of the package variable approach is to use explicit package
+qualified variables.  This has the advantage on old versions of Perl
+that there is no need to load the C<vars> module, but it adds a
+significant typing overhead.  This approach is not suitable for
+registry scripts because they would all be stomping on the C<main::>
+namespace rather than each staying within the namespace allocated to
+them.  And, besides, the overhead of loading the C<vars> module would
+only have to be paid one per Perl interpreter.
 
   multirun2.pl
-  -----------
+  ------------
   #!/usr/bin/perl -w
   
   use strict;
@@ -993,14 +1023,14 @@
   
   sub run {
   
-    $main::counter = 0;
+    $::counter = 0;
   
     increment_counter();
     increment_counter();
   
     sub increment_counter{
-      $main::counter++;
-      print "Counter is equal to $main::counter !\n";
+      $::counter++;
+      print "Counter is equal to $::counter !\n";
     }
   
   } # end of sub run
@@ -1019,10 +1049,11 @@
 and then submit it for your script to process.
 
   multirun3.pl
-  -----------
-  #!/usr/bin/perl -w
+  ------------
+  #!/usr/bin/perl
   
   use strict;
+  use warnings;
   
   for (1..3){
     print "run: [time $_]\n";
@@ -1056,10 +1087,11 @@
 variables in a calling function.
 
   multirun4.pl
-  -----------
-  #!/usr/bin/perl -w
+  ------------
+  #!/usr/bin/perl
   
   use strict;
+  use warnings;
   
   for (1..3){
     print "run: [time $_]\n";
@@ -1092,10 +1124,11 @@
 a literal, e.g. I<increment_counter(5)>).
 
   multirun5.pl
-  -----------
-  #!/usr/bin/perl -w
+  ------------
+  #!/usr/bin/perl
   
   use strict;
+  use warnings;
   
   for (1..3){
     print "run: [time $_]\n";
@@ -1120,14 +1153,27 @@
 
 Here is a solution that avoids the problem entirely by splitting the
 code into two files; the first is really just a wrapper and loader,
-the second file contains the heart of the code.
+the second file contains the heart of the code.  This second file must
+go into a directory in your C<@INC>.  Some people like to put the
+library in the same directory as the script but this assumes that the
+current working directory will be equal to the directory where the
+script is located and also that C<@INC> will contain C<'.'>, neither
+of which are assumptions you should expect to hold in all cases.
+
+Note that the name chosen for the library must be unique thoughout the
+entire server and indeed every server on which you many ever install
+the script.  This solution is probably more trouble than it is worth -
+it is only included here because it was mentioned in previous versions
+of this guide.
 
   multirun6.pl
-  -----------
-  #!/usr/bin/perl -w
+  ------------
+  #!/usr/bin/perl
   
   use strict;
-  require 'multirun6-lib.pl' ;
+  use warnings;
+
+  require 'multirun6-lib.pl';
   
   for (1..3){
     print "run: [time $_]\n";
@@ -1138,7 +1184,8 @@
 
   multirun6-lib.pl
   ----------------
-  use strict ;
+  use strict;
+  use warnings;
   
   my $counter;
 
@@ -1156,7 +1203,53 @@
   
   1 ;
 
-Now you have at least six workarounds to choose from.
+An alternative verion of the above, that mitigates some of the
+disadvantages, is to use a Perl5-style Exporter module rather than a
+Perl4-style library.  The requirement of global uniqueness of the
+module name still applies but at least this is a problem we're already
+familiar with.
+
+  multirun7.pl
+  ------------
+  #!/usr/bin/perl
+  
+  use strict;
+  use warnings;
+  use My::Multirun7;
+  
+  for (1..3){
+    print "run: [time $_]\n";
+    run();
+  }
+
+Separate file:
+
+  My/Multirun7.pm
+  ----------------
+  package My::Multirun7;
+  use strict;
+  use warnings;
+  use base qw( Exporter );
+  our @EXPORT = qw( run );
+
+  my $counter;
+
+  sub run {
+    $counter = 0;
+
+    increment_counter();
+    increment_counter();
+  }
+  
+  sub increment_counter{
+    $counter++;
+    print "Counter is equal to $counter !\n";
+  }
+  
+  1 ;
+
+Now you have at least five workarounds to choose from (not counting
+numbers 2 and 6).
 
 For more information please refer to perlref and perlsub manpages.
 

Reply via email to