Loading ...
Sorry, an error occurred while loading the content.

Re: PATCH porting.pod "First Mystery"

Expand Messages
  • Brian McCauley
    ... No. ... 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
    Message 1 of 20 , Sep 1, 2003
    View Source
    • 0 Attachment
      Stas Bekman <stas@...> writes:

      > nobull@... wrote:
      > > In private mail Stas Bekman <stas@...> 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<my> to C<local> C<our> for all variables for
      > > +which you get the warning. The C<handler> 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
    • Stas Bekman
      Brian McCauley wrote: [...] ... In effect you use local() to undef the variable, instead of explicitly initializing it. Why not doing this explictly? so
      Message 2 of 20 , Sep 2, 2003
      View Source
      • 0 Attachment
        Brian McCauley wrote:
        [...]
        >>Nice, but:
        >>
        >> > +The easiest and the fastest way to solve the nested subroutines
        >> > +problem is to change C<my> to C<local> C<our> for all variables for
        >> > +which you get the warning. The C<handler> 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 Bekman JAm_pH ------> Just Another mod_perl Hacker
        http://stason.org/ mod_perl Guide ---> http://perl.apache.org
        mailto:stas@... 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
      • Brian McCauley
        ... 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
        Message 3 of 20 , Sep 3, 2003
        View Source
        • 0 Attachment
          Stas Bekman <stas@...> writes:

          > Brian McCauley wrote:
          > [...]
          > >>Nice, but:
          > >>
          > >> > +The easiest and the fastest way to solve the nested subroutines
          > >> > +problem is to change C<my> to C<local> C<our> for all variables for
          > >> > +which you get the warning. The C<handler> 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 :-) ! Much more importantly it doesn't
          close the file when the script terminates.

          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.

          > >>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.

          OK, please forget I ever mentioned mp2.

          > [...] I hope that the problem with CWD will be resolved [...]

          The problem with CWD is not that simple.

          The trouble with advising people to create Perl4-style library in the
          same diectory as the script is that it is not intuatively obvious that
          the leafname of that library needs to unique for each ported CGI
          script. That's not just unique within the directory. It's not even
          just unique accross the whole server. It needs to be unique across all
          servers on which the script may ever be installed!

          This namespace problem is not new to Perl programmers. It is, indeed,
          exactly the same problem as the naming of modules. So why not spend
          the extra minuite or so of effort to make a proper Perl5-style library
          (i.e. a module using Exporter) instead and reduce two problems to one.

          Furthermore consider an inexperienced Perl programmer who rips the
          guts out of a GCI script into a Perl4-style library. There's a strong
          chance that he'll then think "hey, I've got this library now, let's
          use it in another CGI script too". This, of course, will produce a
          script that works under CGI but fails sporadically under mod_perl.

          I'm not inventing these problems. I've dealt with the fallout from
          the current porting guide in comp.lang.perl.* a few times.

          Far better not to expose people to the Perl4-style library solution at
          all (except perhaps to warn them against it).

          In the post-patch version of 'porting' I give them a simple choice:

          First choice - move the guts of your CGI into modules. (This is in
          fact 95% of the way to porting your script to a native mod_perl
          hander).

          Second choice - leave the script 99.9% untouched but use localised
          package variables for any variables that are, in the design of the
          script, already global.

          > If you think that using globals + their initialization is a better
          > solution,

          No, initialization is not a good solution. Finalisation is what is
          wanted.

          The use of term "global" to refer to Perl's package variables is
          misleading.

          From the point of view of program design file-scoped lexicals are
          global variables. By suggesting the use of package variables I'm not
          suggesting that anyone start using the programming technique of global
          variables in place of something else. What we are dealing with here
          is the situation where one has a CGI script that already has a design
          that uses global variables. These global variables happen to be
          implemented as file-scoped lexicals.

          To port this script to run as a mod_perl registry script the
          _simplest_ change is just to choose to implement these variables as
          localised package variables instead.

          > [...] we can replace the lib.pl solution with it,

          Good.

          > but should add it to the perl reference section.

          I can't work out what "it" referrs to above. Both solutions should
          appear in the perl reference section. The lib.pl solution should not
          appear in porting, and even if it did then it defintely should not be
          described by saying: "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,..." because
          that's simply untrue (on two counts).

          "Move the code into a separate file" is not "all you have to do".
          Before you can do that you have to choose a globally unique filename
          for your file. And remember I mean _globally_ unique - it must not
          clash with one used in any other registry script on any server where
          the script will ever be installed.

          Even if "move the code into a separate file" _was_ all you had to do
          that would still be a couple of orders of magnitude more effort than
          the "local our" solution thus it would still not be "the easiest and
          the fastest way".


          --
          Reporting bugs: http://perl.apache.org/bugs/
          Mail list info: http://perl.apache.org/maillist/modperl.html
        • Stas Bekman
          [...] ... local is perl4-ism, nowadays it s used only for localizing special perl variables, like $|. ... Agreed, but it s not the proper change, your change
          Message 4 of 20 , Sep 3, 2003
          View Source
          • 0 Attachment
            [...]
            >>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:stas@... 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
          • Perrin Harkins
            ... 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. ... May
            Message 5 of 20 , Sep 3, 2003
            View Source
            • 0 Attachment
              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
            • Stas Bekman
              ... 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
              Message 6 of 20 , Sep 3, 2003
              View Source
              • 0 Attachment
                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 Bekman JAm_pH ------> Just Another mod_perl Hacker
                http://stason.org/ mod_perl Guide ---> http://perl.apache.org
                mailto:stas@... 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
              • Brian McCauley
                ... 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
                Message 7 of 20 , Sep 5, 2003
                View Source
                • 0 Attachment
                  Stas Bekman <stas@...> 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 right thing.

                  You might think you could simply undef($thing) at the end of the
                  script but you'd have to ensure all exection paths, including
                  abnormal termination, pass through the undef statement.

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

                  I'm glad we agree on something :-)

                  > 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.

                  Since the 'my' that is being replaced by 'local our' also initializes
                  variables to undef I don't think we need to labour the point. As I
                  said above, we should assume a working CGI script as the starting
                  point.

                  > - 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?

                  Yes, basically.

                  Revised patch to follow at some point this weekend.


                  --
                  Reporting bugs: http://perl.apache.org/bugs/
                  Mail list info: http://perl.apache.org/maillist/modperl.html
                • Stas Bekman
                  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
                  Message 8 of 20 , Sep 5, 2003
                  View Source
                  • 0 Attachment
                    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 Bekman JAm_pH ------> Just Another mod_perl Hacker
                    http://stason.org/ mod_perl Guide ---> http://perl.apache.org
                    mailto:stas@... 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
                  • Brian McCauley
                    ... 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
                    Message 9 of 20 , Oct 10, 2003
                    View Source
                    • 0 Attachment
                      Stas Bekman <stas@...> 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.

                      > - 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.

                      > [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]

                      Well I disagree with you about it being good a practice. I personally
                      consider it good practice to work in a way that minimises the number
                      of things you have to do explicitly (with the exception of
                      declarations). I can't see why you think relying on the fact that
                      local() will initialize variables to undef is any worse than relying
                      on the fact that my() will.

                      But this is your document so I shall go along with your preferences.

                      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.

                      --- porting.pod.orig Fri Oct 10 18:58:48 2003
                      +++ porting.pod Fri Oct 10 18:42:27 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,66 @@

                      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 from lexical scope to package scope for all
                      +variables for which you get the warning. 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 often redundant for lexical variables it is usually
                      +not redundant for these package variables as they are reused in
                      +subsequent executions of the 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 shared variable contains a reference it my 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;
                      +
                      +As side effect, if you use C<local> you no longer need to add explicit
                      +initialization of variables to undef.
                      +
                      +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

                      --
                      \\ ( )
                      . _\\__[oo
                      .__/ \\ /\@
                      . l___\\
                      # ll l\\
                      ###LL LL\\
                    • Stas Bekman
                      ... 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...
                      Message 10 of 20 , Oct 14, 2003
                      View Source
                      • 0 Attachment
                        Brian McCauley wrote:
                        > Stas Bekman <stas@...> 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...

                        >>- 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.
                        >
                        >
                        >>[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]
                        >
                        >
                        > Well I disagree with you about it being good a practice. I personally
                        > consider it good practice to work in a way that minimises the number
                        > of things you have to do explicitly (with the exception of
                        > declarations). I can't see why you think relying on the fact that
                        > local() will initialize variables to undef is any worse than relying
                        > on the fact that my() will.
                        >
                        > But 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. 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. 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'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. Please remember that this docs is used as a
                        reference by users of varying expertise in Perl. Unless you are an advanced
                        user and know what you are doing, it's a goodness to always initialize
                        variables before you use them.

                        > +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.

                        or something like that? package scope is lexical scope too.

                        > +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
                        > +subsequent 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.

                        > +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? shared variables are special with ithreads and allow sharing data
                        across threads.

                        also s/my/may/

                        The rest looks good. Thanks Brian.

                        __________________________________________________________________
                        Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
                        http://stason.org/ mod_perl Guide ---> http://perl.apache.org
                        mailto:stas@... http://use.perl.org http://apacheweek.com
                        http://modperlbook.org http://apache.org http://ticketmaster.com
                      • Brian McCauley
                        ... Yep, OK. ... I assume that was a typo :-) s/declare/initialize/. ... Hey, I ve conceded. You can stop trying to beat me into submission now. ... I
                        Message 11 of 20 , Oct 15, 2003
                        View Source
                        • 0 Attachment
                          Stas Bekman <stas@...> writes:

                          > Brian McCauley wrote:
                          > > Stas Bekman <stas@...> 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
                        • Stas Bekman
                          ... [...] ... Yes, thank you! ... When did I say that initializing to undef is good thing? I was talking about initializing variables to the types there are
                          Message 12 of 20 , Oct 15, 2003
                          View Source
                          • 0 Attachment
                            Brian McCauley wrote:
                            > Stas Bekman <stas@...> writes:
                            [...]
                            >>>[...] 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/.

                            Yes, thank you!

                            >>>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()?".

                            When did I say that initializing to undef is good thing? I was talking about
                            initializing variables to the types there are going to use, e.g.:

                            my $counter = 0; # numbers
                            my $string = ''; # strings

                            > 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.

                            Most likely we both try to say the same thing, but misunderstanding each other...

                            >>>+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 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.


                            > 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".

                            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?

                            >>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.

                            sounds good.

                            >>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.

                            See my comment above.

                            >>>+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".

                            Agreed.

                            >>>+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_

                            OK

                            __________________________________________________________________
                            Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
                            http://stason.org/ mod_perl Guide ---> http://perl.apache.org
                            mailto:stas@... http://use.perl.org http://apacheweek.com
                            http://modperlbook.org http://apache.org http://ticketmaster.com
                          • Stas Bekman
                            Following our discussion of what kind our -declared vars are, it s interesting that today on p5p there is this thread where all kind of /(package|file) scope
                            Message 13 of 20 , Oct 20, 2003
                            View Source
                            • 0 Attachment
                              Following our discussion of what kind 'our'-declared vars are, it's
                              interesting that today on p5p there is this thread where all kind of
                              /(package|file) scope (lexical)? variable/ are discussed.

                              http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2003-10/msg00912.html

                              __________________________________________________________________
                              Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
                              http://stason.org/ mod_perl Guide ---> http://perl.apache.org
                              mailto:stas@... http://use.perl.org http://apacheweek.com
                              http://modperlbook.org http://apache.org http://ticketmaster.com
                            • Brian McCauley
                              ... OK, I still find the strict English grammar easier to read in this instance, but I ll go with your form. ... I m sorry I have no idea where that came form.
                              Message 14 of 20 , Oct 24, 2003
                              View Source
                              • 0 Attachment
                                Stas Bekman <stas@...> 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
                              • Jacob Fugal
                                (sorry Brian, this was supposed to go to the list... is there any plan to fix the reply-to header on this list?) ... I know, as a newbie to the list, I
                                Message 15 of 20 , Oct 24, 2003
                                View Source
                                • 0 Attachment
                                  (sorry Brian, this was supposed to go to the list... is there any plan
                                  to fix the reply-to header on this list?)

                                  Brian McCauley wrote:
                                  > Stas Bekman <stas@...> 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 know, as a newbie to the list, I probably won't have much sway in
                                  this, but I have to agree with Brian. I read the version above -- the
                                  one with commas -- and it just isn't working for me. My brain just won't
                                  parse that as correct English (or even Englilsh). If I remember my
                                  grammar correctly, you only use commas to set of a descriptive phrase
                                  when it's a noun clause (such as "my friend's cousin", "the big red one
                                  over there", etc.). Prepositional phrases should flow inline with the
                                  noun being described. That's why there're no commas. It becomes, "every
                                  lexically scoped variable you get the error for," if you're not going to
                                  mind the misuse of the preposition. I'd be fine with that under most
                                  circumstances, but the following context makes it weird, which was
                                  probably Brian's original point. Switching to correct use of the
                                  preposition, "for which", fixes that. "...switch every lexically scoped
                                  variable for which you get the warning to a..."

                                  It's not affected -- it's correct. We American's sometimes think of
                                  correct grammar as affected (myself included), but sometimes it's
                                  correct anyways and it actually makes things easier to understand.

                                  Ok, enough of my english rant, flame on :)

                                  Jacob Fugal
                                • Geoffrey Young
                                  ... welcome. in general, this list is very welcoming to newbies. so, please don t take what I m about to say as being directed toward you... [ elements of
                                  Message 16 of 20 , Oct 24, 2003
                                  View Source
                                  • 0 Attachment
                                    > I know, as a newbie to the list,

                                    welcome.

                                    in general, this list is very welcoming to newbies. so, please don't take
                                    what I'm about to say as being directed toward you...

                                    ['elements of style' excerpts snipped]

                                    you know, if y'all spent less time squibbling over minor grammatical points,
                                    and instead channeled all this free energy and tuits into augmenting the
                                    docs with new material, everyone would be better off.

                                    --Geoff
                                  • Jacob Fugal
                                    ... Thanks. ... Agreed :) Unfortunately, I m rather a beginner with modperl -- hence my subscription to this list -- and don t feel comfortable submitting
                                    Message 17 of 20 , Oct 24, 2003
                                    View Source
                                    • 0 Attachment
                                      Geoffrey Young wrote:
                                      >
                                      >> I know, as a newbie to the list,
                                      >
                                      >
                                      > welcome.

                                      Thanks.

                                      > in general, this list is very welcoming to newbies. so, please don't
                                      > take what I'm about to say as being directed toward you...
                                      >
                                      > ['elements of style' excerpts snipped]
                                      >
                                      > you know, if y'all spent less time squibbling over minor grammatical
                                      > points, and instead channeled all this free energy and tuits into
                                      > augmenting the docs with new material, everyone would be better off.

                                      Agreed :) Unfortunately, I'm rather a beginner with modperl -- hence my
                                      subscription to this list -- and don't feel comfortable submitting
                                      documentation yet. But hopefully I can and will soon.

                                      Jacob
                                    • Stas Bekman
                                      ... All I wanted to say is that my wording reads better if using commas. I didn t imply that it was better than yours, when using commas. Your wording was just
                                      Message 18 of 20 , Oct 24, 2003
                                      View Source
                                      • 0 Attachment
                                        Brian McCauley wrote:
                                        > Stas Bekman <stas@...> 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.

                                        All I wanted to say is that my wording reads better if using commas. I didn't
                                        imply that it was better than yours, when using commas. Your wording was just
                                        fine (and certainly better then mine ;)

                                        [...]

                                        Agreed with the rest of remaining comments to the ongoing comments ;)

                                        > 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. Unless you think that it'll take a long time
                                        before you will come up with perl_reference.pod patches, in which I can I
                                        guess we can commit this one right now.

                                        Thanks Brian!

                                        __________________________________________________________________
                                        Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
                                        http://stason.org/ mod_perl Guide ---> http://perl.apache.org
                                        mailto:stas@... http://use.perl.org http://apacheweek.com
                                        http://modperlbook.org http://apache.org http://ticketmaster.com
                                      Your message has been successfully submitted and would be delivered to recipients shortly.