From: Michael Carman Date: Fri, 21 Sep 2001 17:54:05 +0000 (-0500) Subject: Re: [ID 20010919.001] local() fails on imported variables X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=5e76a0e22d491fe53448ba9354da709fef4051d1;p=p5sagit%2Fp5-mst-13.2.git Re: [ID 20010919.001] local() fails on imported variables Message-Id: <3BABC50D.6040202@home.com> (Applied with some changes.) p4raw-id: //depot/perl@12125 --- diff --git a/pod/perlmod.pod b/pod/perlmod.pod index 29ad67c..b27ee85 100644 --- a/pod/perlmod.pod +++ b/pod/perlmod.pod @@ -120,7 +120,43 @@ subroutine, assign a reference instead: Which makes $richard and $dick the same variable, but leaves @richard and @dick as separate arrays. Tricky, eh? -This mechanism may be used to pass and return cheap references +There is one subtle difference between the following statements: + + *foo = *bar; + *foo = \$bar; + +C<*foo = *bar> makes the typeglobs themselves synonymous while +C<*foo = \$bar> makes the SCALAR portions of two distinct typeglobs +refer to the same scalar value. This means that the following code: + + $bar = 1; + *foo = \$bar; # Make $foo an alias for $bar + + { + local $bar = 2; # Restrict changes to block + print $foo; # Prints '1'! + } + +Would print '1', because C<$foo> holds a reference to the I +C<$bar> -- the one that was stuffed away by C and which will be +restored when the block ends. Because variables are accessed through the +typeglob, you can use C<*foo = *bar> to create an alias which can be +localized. (But be aware that this means you can't have a separate +C<@foo> and C<@bar>, etc.) + +What makes all of this important is that the Exporter module uses glob +aliasing as the import/export mechanism. Whether or not you can properly +localize a variable that has been exported from a module depends on how +it was exported: + + @EXPORT = qw($FOO); # Usual form, can't be localized + @EXPORT = qw(*FOO); # Can be localized + +You can work around the first case by using the fully qualified name +(C<$Package::FOO>) where you need a local value, or by overriding it +by saying C<*FOO = *Package::FOO> in your script. + +The C<*x = \$y> mechanism may be used to pass and return cheap references into or from subroutines if you don't want to copy the whole thing. It only works when assigning to dynamic variables, not lexicals.