Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: hash-keys have lost their class information

Tags:

class

key

hash

perl

I have a package X.pm with a method data_x();
I use instances of class X as keys of a hash %seen, say.
Now the elements of keys %seen seem to have forgotten their blessing:

use X;

my( $x, $y, %seen );

$x = X->new();
$x->data_x( 1 );

print " x:      ", $x, "\n";
print " x.data: ", $x->data_x(), "\n";

$seen{ $x } = 1;
$y = (keys %seen)[0];

print " y:      ", $y, "\n";
print " y.data: ", $y->data_x(), "\n";

This prints:

 x:      X=HASH(0x228fd48)
 x.data: 1
 y:      X=HASH(0x228fd48)
Can't locate object method "data_x" via package "X=HASH(0x228fd48)"
(perhaps you forgot to load "X=HASH(0x228fd48)"?) at test.pl line 15.

Both $x and $y point to the same address, but apparently keys did not copy the class info.
Why is that so?

like image 607
Klaus Avatar asked Dec 16 '22 20:12

Klaus


1 Answers

They did not only lose their blessing, they are not even hashrefs anymore.

You can only use strings as hash keys in Perl.

Everything that is not already a string will be made into a string. So the key in the hash is not an object anymore, but the string 'X=HASH(0x228fd48)' (which is what a blessed hashref looks like when printed). There is no way to get the object back from that string (unless you have another hash which maps these keys to original objects).

You need to use a unique identifier as the hash key instead. It appears that you can use the current string version (which is basically a memory address) to at least check for object identity (the object does not seem to be moved around while it is alive), but I am not sure how stable that would be (some implementation of inside-out objects seem to be based on this idea, though), and it does not give you object equality checks.

like image 144
Thilo Avatar answered Jan 30 '23 08:01

Thilo