From 5e76a0e22d491fe53448ba9354da709fef4051d1 Mon Sep 17 00:00:00 2001 From: Michael Carman Date: Fri, 21 Sep 2001 12:54:05 -0500 Subject: [PATCH] Re: [ID 20010919.001] local() fails on imported variables Message-Id: <3BABC50D.6040202@home.com> (Applied with some changes.) p4raw-id: //depot/perl@12125 --- pod/perlmod.pod | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) 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. -- 1.8.3.1