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

54352Re: PATCH porting.pod "First Mystery"

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