Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

deleting glob does not undef values?

by bdimych (Monk)
on Nov 22, 2007 at 13:28 UTC ( #652367=perlquestion: print w/replies, xml ) Need Help??

bdimych has asked for the wisdom of the Perl Monks concerning the following question:

Sorry, may be stupid,
$A::bbb = 3; delete $A::{bbb}; print $A::bbb;
prints 3

I did not expect this, I thought if glob deleted, then all values should be undef at the next access. Is it ok, where can I read about such behaviour?

Replies are listed 'Best First'.
Re: deleting glob does not undef values?
by dave_the_m (Monsignor) on Nov 22, 2007 at 15:15 UTC
    delete $A::{bbb} deletes an entry from the %A:: stash, which means that there is one less reference to the *A::b glob. However, for effeciency the GVSV op (as executed in $A::bbb) doesn't lookup the stash at runtime, but instead at compile time it caches a direct pointer to the glob. These references to the glob ensure that it doesn't go away. An eval shows the difference:
    $A::bbb = 3; delete $A::{bbb}; printf "direct=%d eval=%d\n", $A::bbb, eval q{$A::bbb}; outputs: direct=3 eval=0


Re: deleting glob does not undef values?
by shmem (Chancellor) on Nov 22, 2007 at 15:34 UTC
    $A::{bbb} is not what you think it is:
    $A::{bbb} = 3; print $A::bbb; __END__

    Nothing. And

    $A::{bbb} = 3; $A::bbb = 4; __END__ Modification of a read-only value attempted at - line 2.


    $A::bbb = 3; $A::{bbb} = 4; print "$_ => $A::{$_}\n" for keys %A::; print $A::bbb,"\n"; __END__ bbb => *main::4

    What's happening here? The %A:: has typeglobs as values, so assigning $A::{bbb} = 4 makes the literal 4 into a typeglob of the symbol table %main::. There's the glob, the typeglob entry in the symbol table, and the value in the glob's slot:

    $A::bbb = 3; print $A::{bbb},"\n"; print *A::bbb{SCALAR},"\n"; print ${*A::bbb{SCALAR}},"\n"; __END__ *A::bbb SCALAR(0xa011750) 3

    The special hash %A:: holds references to the typeglobs , these entries aren't the typeglobs themselves. but by deleting those entries you don't delete the glob. You mangle the lookup table only. their reference count must not go to zero. Since - as per your example - there's $A::bbb still present in compiled code, its reference count doesn't go to zero. So it is still accessible.

    update: corrected above paragraph as per ysth's comment below. Thanks, ysth!


    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      The special hash %A:: holds references to the typeglobs, these entries aren't the typeglobs themselves.
      No, they are the typeglobs themselves (or other things in some special cases, which means extreme care must be taken when directly accessing a symbol table). But globs are looked up and pointers to them inserted into code that uses variables of that name at compile time. delete does remove the glob from the symbol table hash, but the glob isn't freed if it is referenced by compiled code; any code compiled thereafter will create and reference a new glob, though.

      You can see this in action:

      $ perl -wle'use Devel::Peek "SvREFCNT"; $A = "foo"; BEGIN { print SvRE +FCNT($::{A}) } $A = "bar"; BEGIN { print SvREFCNT($::{A}) } delete $: +:{A}; eval "\$A = 1; print SvREFCNT(\$::{A})"' 2 3 2
      (One refcnt is held by the symbol table; additional ones are added for each reference in the code. The delete removes the glob from the symbol table, but it isn't freed since it still has 2 references.)
Re: deleting glob does not undef values?
by dk (Chaplain) on Nov 22, 2007 at 14:12 UTC
    It seems to me that delete doesn't work on stashes (%A:: in your case), only on hashes. Use either $A::bbb = undef as suggested above, or  { local $A::bbb = 3 }

    But actually, this is a good point: why doesn't it work on stashes? That's a nice feature.

Re: deleting glob does not undef values?
by okram (Monk) on Nov 22, 2007 at 14:01 UTC
    What you want is undef, as in:
    undef $ENTITY;
Re: deleting glob does not undef values?
by cdarke (Prior) on Nov 22, 2007 at 13:54 UTC
    delete does not do what you are assuming - this is not C++. delete removes key/value pairs from a hash, or element values from an array.

    Update:No, it's me who's read it wrong - $A::{bbb} is an element, otherwise it would give a warning - sorry.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://652367]
Approved by Corion
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (2)
As of 2023-09-23 17:48 GMT
Find Nodes?
    Voting Booth?

    No recent polls found