in reply to Re: Re: local element of my() array????
in thread local element of my() array????
For package vars, this primary access path is the glob. Each package contains a glob for each name that occurs in it. This glob can contain a scalar variable, a hash variable, an array variable, an IO handle etc.
When you do local $Foo; (where $Foo is a package var) perl will save the original scalar variable (not its contents) on stack, create a new scalar variable, and insert it into the glob's SCALAR field. It will also increment the refcount on the glob so it will surely not be deallocated.
•(Update: a local doesn't get initialized with the original value... I thought it was..)
On return, the localized variable is discarded, the original variable is placed back in the glob, and the glob's refcount is decremented. Everything is back to normal.
Note that you can easily see this behavior: just take a reference to $Foo before and after localizing it. You'll see they reference different and independent variables. (Keeping a reference to the localized var will ofcourse keep it alive, even if the local has already been restored
The procedure is identical for local %Foo and local @Foo, except they operate on the HASH and ARRAY fields of the glob. When you do local *Foo, it does essentially the same procedure but for all fields of the glob at once. They're put together in a structure to which the glob keeps a pointer, so it doesn't need to save each var separately. Note that it can't just allocate a new glob and place it into the package, since all existing code would still use the old glob, which they reference directly.
Now for lexical variables... they have no glob! :-)
That doesn't mean it's truly impossible to localize them (I haven't examined how my-vars are implemented exactly), but it surely means that the mechanism described above can not be reused for them.
As I mentioned in my original note, localizing array and hash elements works completely different. Here you specify an array or hash in any way you like, and the index or key of an element. local $foo[3] then takes the scalar variable (again, not its contents) which is the element at that index (or key), saves it on the stack, along with a reference to the array/hash (which also means the array/hash will surely not get destroyed) and the index/key of the element. It creates a new scalar variable and places in the original location. When the block ends, it places the saves element back, discarding the variable that was there.
Again, you can check this by taking a reference. You'll see that the localized $foo[3] is a different and independent variable than the original.
Ok, that's it I think... any questions? :-)
•Update: Here's some example code with output:
Gives this output (I added comments):$\ = "\n"; # automatically add newlines to output $Foo = 4; # create the var print '*Foo{SCALAR} = ', *Foo{SCALAR}; # print the glob entry my $x = \$Foo; # make a reference... which is print '$x = ', $x; # the same as the glob entry.. duh $$x = 5; # change via reference print '$Foo = ', $Foo; # var has changed my $y; print "Enter scope"; { local $Foo = 42; # let the magic begin! print '*Foo{SCALAR} = ', *Foo{SCALAR}; # it's different! $y = \$Foo; # take a ref to this new thing print '$y = ', $y; # the same as the *new* glob entry print '$Foo = ', $Foo; # foo is 42 print '$$x = ', $$x; # print old var via reference.. unchanged print '$$y = ', $$y; # print new var via reference.. it's 42 $$x = 6; # change via reference to *old* print '$Foo = ', $Foo; # nothing happened to the local one! # but wait... } print "Exit scope"; print '*Foo{SCALAR} = ', *Foo{SCALAR}; # old glob entry is back print '$Foo = ', $Foo; # and we changed this one via $x earlier! print '$y = ', $y; # now the last remaining reference to local va +r print '$$y = ', $$y; # still 42
*Foo{SCALAR} = SCALAR(0x511f4) # original entry in glob $x = SCALAR(0x511f4) # ref to original scalar (same) $Foo = 5 # original value Enter scope *Foo{SCALAR} = SCALAR(0x47650) # new SCALAR entry in glob $y = SCALAR(0x47650) # ref to it $Foo = 42 # value of localized var $$x = 5 # value of original $$y = 42 # value via ref to localized var $Foo = 42 # after editing original, local unchan +ged Exit scope *Foo{SCALAR} = SCALAR(0x511f4) # original entry back in glob $Foo = 6 # change we made via $$x now visible $y = SCALAR(0x47650) # the localized var still around via r +ef $$y = 42 # still contains value
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Bravo!
by Anonymous Monk on Feb 19, 2003 at 16:36 UTC |