[VPM] testing two refs for same target

Michael S. Joyce michael at negativespace.net
Fri Jul 4 22:10:31 CDT 2003


I has been quite a while since I've done any real Perl, but here goes. I
don't consider myself a guru.

> 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.

> The context is that I have an array of references to objects
>  and also a scalar having a reference to one of the same objects
>  in the array; I want to remove the identified object from the 
> list, so I need to know which one it is.
> 
> 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"?  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.

> 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.

> 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.	

> Essentially, I'm sort of exploring new territory here.
> 
> Thanks for any answers.

You're welcome.

> BTW, I plan to upload tonight the first version of SQL::ObjectModel (name 
> registration pending; used by Rosetta) which one can actually use for 
> something (not just documentation), although it will be at alpha development
> status.  This class is an unserialized representation of SQL, and would 
> be the standard way of formatting database commands for Rosetta to 
> execute.  My main question above relates to deleting the link from a 
> node's parent to itself.
> 
> Have a good day. -- Darren Duncan
> 

Thank you. I've a weekend with no homework. I'm very excited.

Michael




More information about the Victoria-pm mailing list