Item 23: Understand the difference between my and local .


Item 23: Understand the difference between my and local .

The difference between my and local is one of the more subtle and difficult aspects of Perl. It is subtle because the occasions when you can observe functional differences between my and local are somewhat infrequent. It is difficult because the differences in behavior that do result can be unexpected and very hard to understand.

People sometimes state the difference between my and local as something like " my variables only affect the subroutine they're declared in, while local variables affect all the subroutines called from that subroutine." But this is wrong , because my has nothing to do with subroutines, local has nothing to do with subroutines, and of course the difference between them has nothing to do with subroutines. It may look that way, but the truthas you will seeis something else entirely. Nevertheless, I am treating local and my in this section because their use in subroutines is extremely important.

Global variables

In Perl, all variables, subroutines, and other entities that can be named have package scope (or just " global scope") by default. That is, they exist in the symbol table of some package. Braces, subroutines, and/or files alone do not create local variables. [1] (For more about packages and symbol tables, see Item 42 and Item 57.)

[1] Certain constructs like foreach and map do automatically localize iteration variables. Seems like for every rule, there's a quasi-exception.

In most cases, global names are placed in the appropriate package symbol table during the compilation phase. Names that cannot be seen at compile time are inserted during execution. Let's run a program named tryme to see: [2]

[2] You can also use the debugger for this (see Item 39), but these examples were easier for me to illustrate in the text with short programs.

Print out the contents of the main symbol table ( %main:: , a.k.a. %:: ).

 print join " ", keys %::;  $compile_time;  ${"run_time"}; 

Created at compile time.

Soft ref (see Item 30 ), created at run time.

 %  tryme  ARGV 0 FileHandle:: @ stdin STDIN " stdout STDOUT $ stderr  STDERR _<perlmain.c compile_time DynaLoader::  _<tryme ENV  main:: INC DB:: _ / 

Notice, in this example, that the identifier compile_time is present in the symbol table before the variable $compile_time is actually reached during execution. If you were unsure of Perl's compiler-like nature before, an example like this should confirm it to you.

You've probably been told since almost the beginning of your programming career (or hobby, or however you prefer to describe it) that global variables are bad . Good programs shouldn't use a lot of global variables, the saying goes, because global variables create hidden interfaces, make code difficult to read and modify, and even make it hard for compilers to optimize your code.

You may or may not agree completely with this. However, I'm sure that if you have written programs longer than a few hundred lines, especially as part of a team effort, you'll agree with it at least partially. You should see the need for a mechanism to support local variables in Perl. Of course, Perl does support local variables, and in fact is more generous in its support than most languages. Most languages give you only a single mechanism for creating local variables. Perl gives you two.

Lexical (compile-time) scoping with my

Perl's my operator creates variables with lexical scope. A variable created with my exists from the point of declaration through the end of the enclosing scope. An enclosing scope is a pair of braces, a file, or an eval string (see Item 54). The scope is lexical in that it is determined solely by an inspection of the program text during compilation. Another way of saying this is that the scope of a my variable can be determined by simply looking at the source code. For example:

graphics/05fig01.gif

Here, the variable $a in use outside the braces is the global $a . The variable $a inside the braces is the lexical $a , which is local to those braces. Now, if this seems amazingly obvious and mundane to you, well, it should. This is the way that most commonly used programming languages handle scopes. But this is Perl, and you shouldn't be surprised to hear that there are a few wrinkles. In fact, there are more than a few wrinkles . Let's look at some of them.

First, let's revisit our inspection of the symbol table. Here's a program similar to the one at the beginning of this Item but with things reordered a bit. This time we'll use my :

 my $compile_time;  $compile_time;  print join " ", keys (%::); 

This is a my variable.

Use it.

This time, when we run it, we get:

 %  tryme  ARGV 0 FileHandle:: @ stdin STDIN " stdout STDOUT $ stderr  STDERR _<perlmain.c DynaLoader::  _<tryme ENV main:: INC DB:: _  / 

Hmm. Where did compile_time go? Let's look at something else:

 $compile_time;  my $compile_time;  print join " ", keys (%::); 

This isn't a my variable.

But this is.

When we run this example, we get:

 %  tryme  ARGV 0 FileHandle:: @ stdin STDIN " stdout STDOUT $  stderr  STDERR _<perlmain.c compile_time DynaLoader::  _<tryme ENV  main:: INC DB:: _ / 

Now, compile_time is back.

What these examples demonstrate is that my variables do not "live" in the package symbol tables. In the example with my $compile_time first, there is only one variable named $compile_time in the file, and it never gets into the package symbol table. In the other example, there are two separate variables named $compile_time : the global one in the symbol table, and my $compile_time , which is not in a symbol table. [3]

[3] Actually, it's in a compile-time symbol table, but that symbol table is not accessible at run time.

You can always access the value of package globals via qualified names. Qualified names (those containing :: ) always refer to a variable in a symbol table. For example:

 {    my $a = 3.1416;    $main::a = 2.7183;    print "(in) a = $a\n";    print "(in) main::a = $main::a\n";    print "(in) ::a = $::a\n";  }  print "(out) a = $a\n"; 

(in) a = 3.1416

(in) main::a = 2.7183

(in) ::a = 2.7183

(out) a = 2.7183

Symbol tables are also used for a variety of other things including soft references and typeglobs. Because my variables are not in a symbol table, you can't get at them using either technique. Here's a demonstration involving soft references:

 my $a = 3.1416;  ${'a'} = 2.7183;  print "my a = $a\n";  print "{a} = ${'a'}\n"; 

my a = 3.1416

{a} = 2.7183

Typeglobs work the same way. In fact, as this example demonstrates , typeglobs, soft references, and qualified variable names never refer to lexical ( my ) variables:

 $a = 2.7183;  my $a = 3.1416;  *alias = *a;  print "my a = $a\n";  print "alias = $alias\n";  print "{a} = ${'a'}\n";  print "::a = $::a\n"; 

my a = 3.1416

alias = 2.7183

{a} = 2.7183

::a = 2.7183

Notice that the *alias typeglob refers to the global *a , even though the typeglob assignment comes after my $a . It makes no difference where the assignment comesa typeglob always refers to an entry in the symbol table, and my variables aren't going to be there. The rest of the wrinkles have to wait until we have begun discussing local variables.

Run-time scoping with local

Perl's other scoping mechanism is local . local has been around a lot longer than my . In fact, my was introduced only in Perl 5. What, you may wonder , is so wrong with local that Larry Wall felt it worthwhile to add an entirely different scoping mechanism to supplant it? To answer this question, let's just look at how local works. At some point you will start to see the virtues of my .

local is a run-time scoping mechanism. [4] Unlike my , which basically creates new variables in a private symbol table during compilation, local has a run-time effect: It saves the values of its arguments on a run-time stack, then restores them when the thread of execution leaves the containing scope. At first glance, local and my appear to do very similar things. Here's an example similar to the one in the box on page 89, with the my replaced by local :

[4] You may hear local called "dynamic scoping" elsewhere, but I believe "run-time scoping" is more accurate and understandable.

 $a = 3.1416;  {    local $a = 2.7183;    print "$a\n";  }  print "$a\n"; 

Here's a simple local example.

2.7183

3.1416

Although this looks like the example with my , and although it produces the same output, something very different is going on in the innards of Perl.

In the case of my , as you have seen, Perl creates a separate variable that cannot be accessed by name at run time. In other words, it never appears in a package symbol table. During the execution of the inner block, the global $a on the outside continues to exist, with its value of 3.1416 , in the symbol table.

In the case of local , however, Perl saves the current contents of $a on a run-time stack. The contents of $a are then replaced by the new value. When the program exits the enclosing block, the values saved by local are restored. There is only one variable named $a in existence throughout the entire example. To better illustrate this, let's use a soft reference to take a peek into the symbol table:

 $a = $b = 3.1416;  {    local $a = 2.7183;    my $b = 2.7183;    print "IN: local a = $a, my b = $b\n";    print "IN: {a} = ${'a'}, {b} = ${'b'}\n";  }  print "OUT: local a = $a, my b = $b\n"; 

Running this produces:

 %  tryme  IN: local a = 2.7183, my b = 2.7183  IN: {a} = 2.7183, {b} = 3.1416  OUT: local a = 3.1416, my b = 3.1416 

How interesting. The trick of using the soft reference to look at the global $a that worked with my seems to have no effect with local . This is as it should be. my creates a different variable , while local temporarily saves the value of the existing one . Because local is a run-time, not a compile-time mechanism, the changes that local makes to global variables can be observed outside the lexical scope containing the local operator. The most notorious example of this is the nested subroutine call:

 $a = 3.1416;  sub print_a { print "a = $a\n" }  sub localize_a {    print "entering localize_a\n";    local $a = 2.7183;    print_a();    print "leaving localize_a\n";  }  print_a();  localize_a();  print_a(); 

Running this yields:

 %  tryme  a = 3.1416  entering localize_a  a = 2.7183  leaving localize_a  a = 3.1416 

This is the oft-cited example that leads to the description of local as having something to do with subroutine calls, which, as I stated earlier, it does not.

When to use my ; when to use local

In general, you should use my rather than local if you have a choice. One reason for this is that my is faster than local . It takes some time to save a value on the stack:

 use Benchmark;  timethese (10, {    'local' => q{for (1..10000) {local $a = $_; $a *= 2;} },    'my' => q{for (1..10000) { my $a = $_; $a *= 2;} },  } );  %  tryme  Benchmark: timing 10 iterations of local, my...       local:  5 secs ( 5.04 usr  0.00 sys =  5.04 cpu)         my:  3 secs ( 3.11 usr  0.00 sys =  3.11 cpu) 

Another reason to use my is that it's easier to understand and doesn't create the strange "non-local" side effects that local does.

Yet another reason to use my is that the lexical variables it creates form the basis for closures in Perl (see Item 29).

However, one compelling reason to use local , or at least to be familiar with it, is that there is a lot of Perl 4 code out there that uses it. Replacing local with my isn't as easy as a search and replace with a text editoryou will have to examine each use of local individually to see whether it takes advantage of one of the "features" of local . It is probably best to leave code that uses local alone as long as it is performing well. Also, some things have to be done with local .

Special variablesany $ -punctuation variable or other variable that Perl handles speciallycan only be localized with local . It is an error to attempt to localize a special variable with my :

 sub response {    local $_ = <STDIN>;    /^y/i ? "yes" : "no: $_";  } 

my $_ would be a compile-time error.

local can be used in a number of other situations in which my can't. You can use it on a variable in another package:

 package foo;  $a = 3.1416;  {    package main;    local $foo::a = 2.7183; 

In main package now.

 package foo;    print "foo::a = $a\n";  }  print "foo::a = $a\n"; 

Back to foo package.

foo::a = 2.7183

foo::a = 3.1416

You can also use local on elements of arrays and hashes. Yes, strange but true. You can even use local on a slice:

 @a = qw(Jolly Green Giant);  {    local(@a[0, 1]) = qw(Grumbly Purple);    print "@a\n";  }  print "@a\n"; 

Grumbly Purple Giant

Jolly Green Giant

You can also use local on typeglobs (see Item 57). In theory, local could be made to work on almost any value, but there are limitations in the current implementation. For example, as of this writing you cannot use local on a dereferenced value like $$a .

local and my as list operators

One way in which local and my are the same is syntax. Both local and my can be applied to single scalars, arrays, and hashes:

 local $scalar;  my @array;  local %hash; 

You can initialize a variable while localizing it:

 local $scalar = 3.1416;  my @array = qw(Mary had a little lamb);  local %hash = (    H => 1, He => 2, Li => 3  ); 

If you use parentheses around the argument(s) to my and local , the argument(s) become a list, and assignments are now evaluated in a list context:

 local($foo, $bar, $bletch) = @a 

First 3 elements from @a .

Watch out for the usual list assignment "gotchas":

 local $foo, $bar, $bletch = @a; 

WRONGdon't forget the parens! $bletch gets size of @a ; only $foo is localized.

 my (@a, @b) = @c; 

WRONGlocalizes @a and @b but only @a gets values.

 my ($a) = <STDIN>; 

WRONGreads all of standard input.



Effective Perl Programming. Writing Better Programs with Perl
Effective Perl Programming: Writing Better Programs with Perl
ISBN: 0201419750
EAN: 2147483647
Year: 1996
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net