Closed schwern closed 14 years ago
To clarify
my $obj = Foo->new; my $other = $obj; $obj->id eq $other->id; # true
my $obj = Foo->new; my $other = Foo->new; $obj->id eq $other->id; # false
Whether 42->id eq 42->id is up in the air. Argument against is that \42 will give you a different scalar ref each time. Argument for is that you can't change the contents. Possibly resolved by a stricter definition of object equality.
Simply using the reference of the object is a good first cut, but its not safe as references can be reused.
perl -wle 'my $id; for(1..3) { my $obj = bless {}, "Foo"; print $obj }'
Foo=HASH(0x8039e8)
Foo=HASH(0x8039e8)
Foo=HASH(0x8039e8)
If you store the id of an object, and the object gets destroyed, you might find yourself with a different object but the same id again.
Could an approach like this work? http://gist.github.com/310560
As far as I could tell, it behaves like Ruby's object_id: the id changes when the content of the variable changes, copying the variable to another retains the id, and reusing memory addresses with different content changes the id also.
Update: well, not quite: irb(main):003:0> 5.times { |i| foo = "foo"; puts foo.object_id } -608671988 -608671868 -608671918 -608671998 -608672108 => 5
The problem there is when the contents of the object change, the id change. We want the id to remain immutable over the life of the object.
Your code does bring up the idea of combining the reference with some sort of salt to make it unique. The issue then is storing it. That's what the meta object would be for, but then you have to be able to repeatedly find an object's meta object which requires... an object ID. Catch 22.
Overriding bless() may be the way out. Essentially, bless() checks to see if the freshly minted object has the same ref as a previous object. If so, it appends a simple salt to the id. The down side is this requires recording the ref of every object ever made in the process which will be a memory hog.
@chocolateboy I presume you're suggesting using refaddr() as the ID? Its immutable, but it still relies on reference addresses which Perl will reuse. This means if someone stores an object ID, and the object gets destroyed, its possible a completely unrelated object will get the same ID and cause a false match.
Here's a test. Can you write an id() which passes? http://gist.github.com/335741
The winner is vincent!
{ my $last = 0; Hash::Util::FieldHash::fieldhash(my %id); sub UNIVERSAL::id { my $self = shift; exists $id{$self} ? $id{$self} : ($id{$self} = ++$last) } }
Nice!
I've written Object::ID to implement this independently.
Implemented and will be in 2.2
A method which returns a unique object identifier for any object.
1) What to use? Rumor has it references can get reused. 2) Does reblessing an object change its ident? 3) What should the name be? id() is too generic. object_identifier()?