Stas Bekman <[EMAIL PROTECTED]> writes:

> local is perl4-ism, nowadays it's used only for localizing special
> perl variables, like $|.

Using package variables and local() in to do the job of block-scoped
lexicals is a Perl4-ism.

On the other hand, when using global variables (in which I include
Perl's package variables and Perl's file-scoped lexicals) something
with the semantics of local() is useful.  It is, therefore, annoying
that local cannot be used on lexical variables and even LW has said
that this restriction is artifical and wrong.

I agree that as a programming technique global variables are vulgar.
However the "First Mystery" is all about porting CGI scripts that are
already using global variables (implemented using file-scoped
lexicals).  It is the use of global variables in the first place that
is vulgar, using local() does not make the code any more vulgar.
 
> > Secongly it's a smaller change.
> 
> Agreed, but it's not the proper change, your change can break
> code.

Only in really obscure circumstances.  Of course, if at the same time,
you make an unrelated change that breaks the code I can see how you'd
be tempted to blame me. :-)

> Assuming that we had:
> 
> use warnings;
> my $counter = 0;
> print "hit $counter times";
> 
> Your change:
> 
> use warnings;
> local our $counter;
> print "hit $counter times";

No, that's not my change, I said to change "my" to "local our".  I
didn't say to remove initialization.

> > Anyhow, local() does something quite different.  It undefines it upon
> > exit of the current scope.
>
> On the exit of the scope local() restores the previous value if any,
> and if none was assigned in first place (which implies undef) it's
> reset to undef. 

Yes, I know that.

> I don't think it has anything to do with finalization, it just looks
> like it does.

"Bluebells are not blue, they are actually pink and just look like
they are blue" :-)

I use the term 'finalization' to (amongst other things) refer to
declaring an action that is to take place when a given scope is
removed from the execution stack.  This is what 'local' does.
The word, however, is not important as I don't propose to use it in
the guide.

> However I'm not against your 'local our' solution, I'm just saying
> that it's less obvious than an explicit initialization, even though it
> requires more modification. Not-very advanced users will just get
> confused by this solution. Normally variables need to be initialized
> before they are used, so they will have to init them in any case and
> undef is not what they want.

The porting guide assumes we start with a working CGI script.  If a
variable needs to be initialized to a value other than undef then a
working script must already do so.

> For example we can provide an explicit initialization example

The example in my modified porting.pod already shows explicit
initialization:

  local our $counter = 0;

> after that suggest that you can say 'local our $foo' to globalize and
> localize it at the same time if you prefer to init those to undef via
> local(). Sounds like a good compromise to me.

That fails to mention the real reason for using local.

> > [ about use vars ]
> The guide is written to reduce the number of questions, not raise
> their number. Solution: mention both (our and use vars)

How about we leave the example as I have it now and say:

   In this simple example, 'local' is redundant because $counter is
   explicitly initialized and never holds a reference.  For variables
   that hold references (especially to objects interfacing to entities
   outside Perl) 'local' ensures timely destruction.  For variables
   lacking explicit initialization 'local' also initializes them to
   undefined.

   The 'our' function appeared in 5.6, for backward compatability:

      use vars qw( $counter );
      $counter = 0;

We could also go on to talk about the option of explicitly
initializing variables with undef() to save the minute overhead of
using local() but I think that's unwarranted in porting.pod.  Perhaps
it should be covered in perl_reference.pod.

> > [ file handle example ]
> 
> I didn't suggest that particular use

I realise that the simple file handle example was a poor choice to
illustrate my point.  Here's a better example that could form the
basis of a more verbose explation in perl_reference.pod.

    Suppose you have:

     my $thing = Thing->new;

    Now suppose that Thing objects involve lots of resources (shared
    memory segments, temporary files, large Perl data structures,
    network connections various database/NNTP/SNPP/whatever servers
    and so on) and/or suppose that Thing objects perform some sort of
    output buffering and then flush it in Thing::DESTROY.

    If I change that to:

     our $thing = Thing->new;

    Then all of these resources are held until the script is next run
    or until the interpreter thread is killed.

    If I change it to:

     local our $thing = Thing->new;

    It does the 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

Reply via email to