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

55112Re: PATCH porting.pod "First Mystery"

Expand Messages
  • Brian McCauley
    Oct 24, 2003
      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
    • Show all 20 messages in this topic