From: Rafael Garcia-Suarez Date: Tue, 30 Sep 2003 20:22:02 +0000 (+0000) Subject: Revamp the section on local() in perlsub. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=325192b1501ec5e5c61fcc775e645f404027aa64;p=p5sagit%2Fp5-mst-13.2.git Revamp the section on local() in perlsub. - avoid using the word "declare" in conjunction with local() - less archaelogical references - more about localization of lvalues - removes examples of localization of tied hashes that don't work - give titles to subsections - explain localization of magic values - explain localization of globs - fix link to perldelta p4raw-id: //depot/perl@21392 --- diff --git a/pod/perlsub.pod b/pod/perlsub.pod index 719197e..376ba12 100644 --- a/pod/perlsub.pod +++ b/pod/perlsub.pod @@ -230,7 +230,7 @@ loop (C), subroutine, C, or C'd file. If more than one value is listed, the list must be placed in parentheses. All listed elements must be legal lvalues. Only alphanumeric identifiers may be lexically -scoped--magical built-ins like C<$/> must currently be Cize +scoped--magical built-ins like C<$/> must currently be Cized with C instead. Unlike dynamic variables created by the C operator, lexical @@ -463,17 +463,24 @@ to create private variables that the whole module can see. B: In general, you should be using C instead of C, because it's faster and safer. Exceptions to this include the global punctuation -variables, filehandles and formats, and direct manipulation of the Perl -symbol table itself. Format variables often use C though, as do -other variables whose current value must be visible to called -subroutines. +variables, global filehandles and formats, and direct manipulation of the +Perl symbol table itself. C is mostly used when the current value +of a variable must be visible to called subroutines. Synopsis: - local $foo; # declare $foo dynamically local - local (@wid, %get); # declare list of variables local - local $foo = "flurp"; # declare $foo dynamic, and init it - local @oof = @bar; # declare @oof dynamic, and init it + # localization of values + + local $foo; # make $foo dynamically local + local (@wid, %get); # make list of variables local + local $foo = "flurp"; # make $foo dynamic, and init it + local @oof = @bar; # make @oof dynamic, and init it + + local $hash{key} = "val"; # sets a local value for this hash entry + local ($cond ? $v1 : $v2); # several types of lvalues support + # localization + + # localization of symbols local *FH; # localize $FH, @FH, %FH, &FH ... local *merlyn = *randal; # now $merlyn is really $randal, plus @@ -488,36 +495,26 @@ values to global (meaning package) variables. It does I create a local variable. This is known as dynamic scoping. Lexical scoping is done with C, which works more like C's auto declarations. -If more than one variable is given to C, they must be placed in -parentheses. All listed elements must be legal lvalues. This operator works +Some types of lvalues can be localized as well : hash and array elements +and slices, conditionals (provided that their result is always +localizable), and symbolic references. As for simple variables, this +creates new, dynamically scoped values. + +If more than one variable or expression is given to C, they must be +placed in parentheses. This operator works by saving the current values of those variables in its argument list on a hidden stack and restoring them upon exiting the block, subroutine, or eval. This means that called subroutines can also reference the local variable, but not the global one. The argument list may be assigned to if desired, which allows you to initialize your local variables. (If no initializer is given for a particular variable, it is created with an -undefined value.) Commonly this is used to name the parameters to a -subroutine. Examples: - - for $i ( 0 .. 9 ) { - $digits{$i} = $i; - } - # assume this function uses global %digits hash - parse_num(); - - # now temporarily add to %digits hash - if ($base12) { - # (NOTE: not claiming this is efficient!) - local %digits = (%digits, 't' => 10, 'e' => 11); - parse_num(); # parse_num gets this new %digits! - } - # old %digits restored here +undefined value.) Because C is a run-time operator, it gets executed each time -through a loop. In releases of Perl previous to 5.0, this used more stack -storage each time until the loop was exited. Perl now reclaims the space -each time through, but it's still more efficient to declare your variables -outside the loop. +through a loop. Consequently, it's more efficient to localize your +variables outside the loop. + +=head3 Grammatical note on local() A C is simply a modifier on an lvalue expression. When you assign to a Cized variable, the C doesn't change whether its list is viewed @@ -532,47 +529,63 @@ both supply a list context to the right-hand side, while supplies a scalar context. -A note about C and composite types is in order. Something -like C works by temporarily placing a brand new hash in -the symbol table. The old hash is left alone, but is hidden "behind" -the new one. +=head3 Localization of special variables -This means the old variable is completely invisible via the symbol -table (i.e. the hash entry in the C<*foo> typeglob) for the duration -of the dynamic scope within which the C was seen. This -has the effect of allowing one to temporarily occlude any magic on -composite types. For instance, this will briefly alter a tied -hash to some other implementation: +If you localize a special variable, you'll be giving a new value to it, +but its magic won't go away. That means that all side-effects related +to this magic still work with the localized value. - tie %ahash, 'APackage'; - [...] - { - local %ahash; - tie %ahash, 'BPackage'; - [..called code will see %ahash tied to 'BPackage'..] - { - local %ahash; - [..%ahash is a normal (untied) hash here..] - } +This feature allows code like this to work : + + # Read the whole contents of FILE in $slurp + { local $/ = undef; $slurp = ; } + +Note, however, that this restricts localization of some values ; for +example, the following statement dies, as of perl 5.9.0, with an error +I, because the $1 variable is +magical and read-only : + + local $1 = 2; + +Similarly, but in a way more difficult to spot, the following snippet will +die in perl 5.9.0 : + + sub f { local $_ = "foo"; print } + for ($1) { + # now $_ is aliased to $1, thus is magic and readonly + f(); } - [..%ahash back to its initial tied self again..] -B The code example above does not currently work as described. +See next section for an alternative to this situation. + +B: Localization of tied arrays and hashes does not currently +work as described. This will be fixed in a future release of Perl; in the meantime, avoid code that relies on any particular behaviour of localising tied arrays or hashes (localising individual elements is still okay). -See L for more +See L for more details. -As another example, a custom implementation of C<%ENV> might look -like this: +=head3 Localization of globs - { - local %ENV; - tie %ENV, 'MyOwnEnv'; - [..do your own fancy %ENV manipulation here..] - } - [..normal %ENV behavior here..] +The construct + + local *name; + +creates a whole new symbol table entry for the glob C in the +current package. That means that all variables in its glob slot ($name, +@name, %name, &name, and the C filehandle) are dynamically reset. + +This implies, among other things, that any magic eventually carried by +those variables is locally lost. In other words, saying C +will not have any effect on the internal value of the input record +separator. + +Notably, if you want to work with a brand new value of the default scalar +$_, and avoid the potential problem listed above about $_ previously +carrying a magic value, you should use C instead of C. + +=head3 Localization of elements of composite types It's also worth taking a moment to explain what happens when you Cize a member of a composite type (i.e. an array or hash element).