[VPM] testing two refs for same target

Peter Scott peter at PSDT.com
Sat Jul 5 00:41:46 CDT 2003


Hello from Port Angeles (en route to OSCON/Perl Conference 7).

At 08:10 PM 7/4/2003 -0700, Michael S. Joyce wrote:
> > I wanted to know what the standard or best practice is for comparing two
> > references to see if they point to the same item/object.
>
>Well, a reference in a string context gives you things like
>"ARRAY(0x9384934)". The number is an internal perlism which is supposed
>to uniquely identify the target of the reference. So, if two references
>stringify to the same string, they should be equal.
>
> > What I had thought of was simply doing "$ref1 eq $ref2", but I wanted to
> > know whether there was a better way.
>
>That should work, as eq provides a string context for both operands, so
>the refs get stringified, like above.

Correct.  And in a deliberate bit of magic, == also works (references get 
nummified to unique values as well.  Not hard to guess what values).

> > On a related note, do you know if Perl allows you to remove
> > elements from an array while you are running a foreach loop
> >  on it; for example:
> >
> > foreach my $item (@items) {
> >       if( $item eq $wanted_item ) {
> >               remove_current_item(@items);
> >               last;
> >       }
> > }
>
>I remember reading somewhere that modifying the amount of things in a
>list with foreach was a bad idea, and produced unexpected results. I
>think there was something on perlmonks about it.
>
> > In other words, does Perl have a built-in function like 
> "remove_current_item"?

No.

>Currently I am doing something like this:
> >
> > foreach my $i (0..$#items) {
> >       my $i_to_remove;
> >       if( $items[$i] eq $wanted_item ) {
> >               $i_to_remove = $i;
> >               last;
> >       }
> > }
> > splice( @items, $i_to_remove, 1 );
>
>This is the safe way to do it. You could also use grep.
>
>         @list = grep {$_ ne $wanted_item}, @list
>
>but be warned: that will remove everything that is equal to
>$wanted_item, not just the first one as yours does.

A good example of why some people have wanted to be able to last out of a 
grep block. However, Duncan did say that "one of the items" in the array 
would be the same object.

> > But that looks messier than I would like.
> >
> > On a separate but related question, is it reasonable to use object
> >  references as keys in a hash?  So I could for example, do this:
> >
> > delete( $items{$wanted_item} );
>
>Programming Perl, 2nd edition (the Camel) has a section called "Hard
>References Don't Work as Hash Keys" on p256. The problem is that hash
>keys are stored internally as strings, so when you use a reference as a
>hash key, it gets stringified into "ARRAY(0xSOMETHING)". The interpreter
>is free to move things around in memory, so if you ever go to
>dereference your hash key, you will likely get garbage.
>To quote the camel:
>
>         $x{ \$a } = $a;
>         ($key, $value) = each %x;
>         print $$key;                    #WRONG!
>
>The Perl Cookbook mentions(p486) Tie::RefHash, which is meant to correct
>this problem. I've never used it, so I cannot comment on it. The book
>also makes a reference to Tie::RevHash, but I think that may be a
>misprint.

Yes, it would be.

I've not yet bothered with Tie::RefHash; I usually solve this problem with 
a parallel hash that maps the stringified object to the object itself:

for my $obj (@objects) { $objhash{$obj} = $obj }

In this case, since the hash is replacing an array in the application, 
there's no other data to be associated with the object and so the hash is 
sufficient by itself, i.e., Duncan can do what he wants if he populates the 
hash as above. This is a recognized idiom.

> > Finally, would any of the above actions cause the object
> > references to stringify and no longer be references?
>
>  Stringification doesn't change the actual reference.
>
>         $x = \$a;
>         print "$x"      #stringify $x
>         print $$x;      #still prints whatever was in $a.

Right. Stringification doesn't change anything (unless it's overloaded in a 
very antisocial class). Using the stringified value is the gotcha.
--
Peter Scott
peter at psdt.com
http://www.perldebugged.com




More information about the Victoria-pm mailing list