Forum: Ruby Is it safe to override #hash and #eql? to enable hash key equality?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Bab0a51dbba8f8149b99599802bc0341?d=identicon&s=25 James M. (jamesm17)
on 2009-03-18 19:00
(Received via mailing list)
Hi,

I would like to use object instances as hash keys where two objects
containing the same datum both have the same key value.  This does not
work by default (as expected given that these are two different
instances):

class Foo
  def initialize(datum)
    @datum = datum
  end
end

# Two hash keys for the same datum
a = {Foo.new(:baz) => 1, Foo.new(:baz) => 2}
p a

# => {#<Foo:0x2a95e68888 @datum=:baz>=>1, #<Foo:0x2a95e68860
@datum=:baz>=>2}

However, this functionality can be obtained by overriding Object#hash
and Object#eql?:

class Bar

  attr_reader :datum

  def initialize(datum)
    @datum = datum
  end

  def hash
    @datum.hash
  end

  def eql?(other)
    @datum.eql? other.datum
  end

end

# One hash key for the same datum
b = {Bar.new(:baz) => 1, Bar.new(:baz) => 2}
p b

#=> {#<Bar:0x2a95e684f0 @datum=:baz>=>2}

My simple question is if this is safe/normal/OK for my intentions.
Based on perusal of the online Ruby documentation it looks like #eql?
has been overridden in a number of sub-classes for the same purpose.
But I wanted to get feedback from the community - has anyone here
tried this?  Are there any known side-effects?

Thanks,
-James
Robert Klemme (Guest)
on 2009-03-18 19:05
(Received via mailing list)
On 18.03.2009 18:59, James wrote:
>   end
> and Object#eql?:
>     @datum.hash
> p b
>
> #=> {#<Bar:0x2a95e684f0 @datum=:baz>=>2}
>
> My simple question is if this is safe/normal/OK for my intentions.

Not only that: this is exactly how one should do it.

> Based on perusal of the online Ruby documentation it looks like #eql?
> has been overridden in a number of sub-classes for the same purpose.
> But I wanted to get feedback from the community - has anyone here
> tried this?  Are there any known side-effects?

No, your use is absolutely correct.  This is what this methods are meant
for.  The only thing to remark is this: you can save yourself a lot
typing by doing:

Bar = Struct.new :datum

If you need additional methods in that class you can even do

Bar = Struct.new :datum do
   def another_method
      123
   end
end

Kind regards

  robert
Bab0a51dbba8f8149b99599802bc0341?d=identicon&s=25 James M. (jamesm17)
on 2009-03-18 19:30
(Received via mailing list)
On Mar 18, 11:04 am, Robert Klemme <shortcut...@googlemail.com> wrote:
> Not only that: this is exactly how one should do it.

Excellent - thanks for confirming!
This topic is locked and can not be replied to.