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