Recipe 5.13 Hashing References
5.13.1 Problem
When you use keys on a hash whose keys are
references, the references that keys returns no
longer work. This situation often arises when you want to
cross-reference two different hashes.
5.13.2 Solution
Use Tie::RefHash:
use Tie::RefHash;
tie %hash, "Tie::RefHash";
# you may now use references as the keys to %hash
5.13.3 Discussion
Hash keys are automatically "stringified," that is, treated as though
they appeared between double quotes. With numbers or strings, nothing
is lost. This isn't so with references, though.
Stringified references look like these:
Class::Somewhere=HASH(0x72048)
ARRAY(0x72048)
A stringified reference can't be dereferenced, because it is just a
string and no longer a reference. This means you can't use references
as the keys to a hash without losing their "magic."
Hand-rolled solutions to this problem involve maintaining a distinct
hash whose keys are stringified references and whose values are the
actual references. This is what Tie::RefHash does. We'll use IO
objects for filehandles here to show you that even such strange
references can index a hash tied with Tie::RefHash.
Here's an example:
use Tie::RefHash;
use IO::File;
tie %name, "Tie::RefHash";
foreach $filename ("/etc/termcap", "/vmunix", "/bin/cat") {
$fh = IO::File->new("< $filename") or next;
$name{$fh} = $filename;
}
print "open files: ", join(", ", values %name), "\n";
foreach $file (keys %name) {
seek($file, 0, 2); # seek to the end
printf("%s is %d bytes long.\n", $name{$file}, tell($file));
}
If you're storing objects as the keys to a hash, though, you almost
always should be storing a unique attribute of the object (e.g., name
or ID number) instead.
5.13.4 See Also
The documentation for the standard Tie::RefHash module; the "Warning"
section of perlref(1)
|