ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
10.13. Saving Global ValuesProblemYou need to temporarily save away the value of a global variable. SolutionUse the $age = 18; # global variable if (CONDITION) { local $age = 23; func(); # sees temporary value of 23 } # restore old value at block exit DiscussionUnfortunately, Perl's Still, there are three places where you must use
Using local( ) for temporary values for globalsThe first situation is more apt to happen with predefined, built-in variables than it is with user variables. These are often variables that Perl will use as hints for its high-level operations. In particular, any function that uses Here's an example of using a lot of global variables. The $para = get_paragraph(*FH); # pass filehandle glob $para = get_paragraph(\*FH); # pass filehandle by glob reference $para = get_paragraph(*IO{FH}); # pass filehandle by IO reference sub get_paragraph { my $fh = shift; local $/ = ''; my $paragraph = <$fh>; chomp($paragraph); return $paragraph; } Using local( ) for local handlesThe second situation arises when you need a local filehandle or directory handle, or, rarely, a local function. You can, in post 5.000 Perls, use one of the standard Symbol, Filehandle, or IO::Handle modules, but this simple typeglob technique still works. For example: $contents = get_motd(); sub get_motd { local *MOTD; open(MOTD, "/etc/motd") or die "can't open motd: $!"; local $/ = undef; # slurp full file; local $_ = <MOTD>; close (MOTD); return $_; } If you wanted to return the open filehandle, you'd use: return *MOTD; Using local( ) on parts of aggregatesThe third situation almost never occurs. Because the local operator is really a "save value" operator, you can use it to save off just one element of an array or hash, even if that array or hash is itself a lexical! my @nums = (0 .. 5); sub first { local $nums[3] = 3.14159; second(); } sub second { print "@nums\n"; } second(); The only common use for this kind of thing is for temporary signal handlers. sub first { local $SIG{INT} = 'IGNORE'; second(); } Now while Although a lot of old code uses The With dynamic scoping, a variable is accessible if it's in the current scope - or the scope of any frames (blocks) in its subroutine call stack, as determined at run time. Any functions called have full access to dynamic variables, because they're still globals, just ones with temporary values. Only lexical variables are safe from tampering. If that's not enough reason to change, you might be interested to know that lexicals are about 10 percent faster to access than dynamics. Old code that says: sub func { local($x, $y) = @_; #.... } can almost always be replaced without ill effect by the following: sub func { my($x, $y) = @_; #.... } The only case where code can't be so upgraded is when it relies on dynamic scoping. That would happen if one function called another, and the latter relied upon access to the former's temporary versions of the global variables If you come across old code that uses: &func(*Global_Array); sub func { local(*aliased_array) = shift; for (@aliased_array) { .... } } this should probably be changed into something like this: func(\@Global_Array); sub func { my $array_ref = shift; for (@$array_ref) { .... } } They're using the old pass-the-typeglob strategy devised before Perl support proper references. It's not a pretty thing. See AlsoThe |