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

The most common way to compare object identity in perl is to to a numeric comparison of the object because that examines the memory address for the object. This doesn't work if the object has just passed out of scope - I want to be able to compare identity between two objects which may not both be scope simultaneously. I'd like to write something like this in some test code but as is it isn't sane because if the first object really went out of scope and was recycled then object #2 might just occupy the same slot. Similarly, perhaps object #1 was also stashed somewhere else and *was* still in existance so the identity check would be true. How do I disambiguate this? I want to be able to verify that a new object is not the same object as a potentially destroyed previous object.

my $o1_ident; { my $o1 = object->new; $o1_ident = 0 + $o1; } my $o2 = object->new; my $o2_ident = 0 + $o2; ok( $o1_ident != $o2_ident );

Replies are listed 'Best First'.
Re: Object identity?
by broquaint (Abbot) on Jun 20, 2003 at 12:48 UTC
    To commit what I said in the CB to prosperity:

       There are some functions in overload which might be of interest (in particular StrVal and AddrRef). Also Corion's RFC: Test::Destroy ('Chasing shadows') should provide some further info on overload's functions and working code to boot.
    HTH

    _________
    broquaint

Re: Object identity?
by adrianh (Chancellor) on Jun 20, 2003 at 12:58 UTC

    Not possible in the general case to the best of my knowledge. The only in-built object identifier is the address - so AFAIK there is no way of avoiding the (unlikely) situation of both objects getting the same address without adding some form of unique ID to the class.

    It will also fail if either object overloads +, etc. to return something that is not the address - use refaddr if this is a concern.

    If the reason you want this is to test that an object is being DESTROYed because it falls out of scope you can always use weaken like this.

    I suppose you could do something totally evil, like overriding bless to store a UID somewhere for each object blessed. However this seems excessive :-)

    Can you give us an idea of why you need to do this? I can't think of a situation where it would be necessary (although this is probably just a lack of imagination on my part).

    Of course, if this is only an issue for one class it would be simplest to just add a UID slot to each object.

      The following code is copied directly from Class::WeakSingleton's test.pl. I only care about this for testing so I know that I'm getting the same object when I expect to and not when I don't. I think I'll just put in an object counter and compare *that* since everything else would involve gyrations it seems.

      Added: adrianh said I wasn't clear about what this code shows. If I had a way of comparing past object identity with present objects then I could assert $s1_addr != Class::WeakSingleton->instnace. It turns out that there's a much easier solution which just has me assigning a unique value to each object (just a $counter++) so I can determine identity in the case for my specific problem. The general case may not be solvable.

      { my %h; { # call Class::WeakSingleton->instance() twice and expect to ge +t the same # reference returned on both occasions. my $s1 = Class::WeakSingleton->instance(); my $s2 = Class::WeakSingleton->instance(); ok( $s1 == $s2 ); # Test 4 ok( $s1 == Class::WeakSingleton->instance ); ok( $Class::WeakSingleton::_instance == $s1 ); # Test 5 $h{test} = $s1; } ok( $Class::WeakSingleton::_instance ); # Test 6 } ok( not defined $Class::WeakSingleton::_instance ); # Test 7 { { # call MySingleton->instance() twice and expect to get the sam +e # reference returned on both occasions. my $s3 = DerivedSingleton->instance(); my $s4 = DerivedSingleton->instance(); $s5 = DerivedSingleton->instance; ok( $s3 == $s4 ); ok( $s4 == $s5 ); } ok( $s5 == DerivedSingleton->instance ); undef $s5; ok( not $DerivedSingleton::_instance ); }
        adrianh said I wasn't clear about what this code shows

        I meant to say I didn't understand what you were getting at - apologies :-)

        If I had a way of comparing past object identity with present objects then I could assert $s1_addr != Class::WeakSingleton->instnace.

        If it were me I would check that $s1 had been deallocated using weak references. Something like this example. What you want to test (if I'm reading this correctly) is that the object goes away when it falls out of scope. Having a unique object identifier isn't the only way of doing this.

        It turns out that there's a much easier solution which just has me assigning a unique value to each object

        Not that this is a bad solution either :-)

Re: Object identity?
by graff (Chancellor) on Jun 21, 2003 at 00:14 UTC
    I want to be able to verify that a new object is not the same object as a potentially destroyed previous object.

    If I understand that correctly, then I think I'd prefer to just keep a separate hash of "signatures" for objects as they arise. The object can go out of scope, be destroyed, be overwritten, who cares... I keep an MD5 or checksum of some sort based on the object's content, and if another object arises with the same signature, I have firm and simple proof of the "deja vu", without having to worry about what happened to (de|re)allocated memory since a given object was last seen.