From: Rick DeNatale Date: 2010-12-04T02:28:56+09:00 Subject: Re: hash method how-to? On Thu, Dec 2, 2010 at 5:35 PM, Robert Klemme wrote: > On 12/02/2010 10:46 PM, Yossef Mendelssohn wrote: > >> Although I still think what I was trying to point out is something to >> consider, that simply delegating #hash to an internal element isn't >> all that good because on some level it makes them the same. > > Ultimately all hash values are derived from member hash values.  The key > point - and I believe this is what you want to stress - is _how_ values are > derived.  The methodology applied should strive to yield different hash > values for things that are considered non equivalent.  For example, hash > value of an Array or list implementation should somehow consider position of > elements in order to not return the same hash for two collections which only > differ in ordering.  We can see that Array#hash obeys this: > > irb(main):001:0> [1,2].hash > => 11 > irb(main):002:0> [2,1].hash > => 1 > > On the other hand, since Set conceptually is agnostic of position different > ordering of elements should not create different hash codes: > > irb(main):001:0> require 'set' > => true > irb(main):002:0> s1 = [1,2].to_set > => # > irb(main):003:0> s2 = [2,1].to_set > => # > irb(main):004:0> s1.hash > => 14 > irb(main):005:0> s2.hash > => 14 > irb(main):006:0> s1 == s2 > => true Note that Set, like hash depends on that implication relationship between #hash and #eql? class X attr_reader :name def initialize(name) @name = name end def hash @name.hash end def inspect "X:#{@name.inspect}" end end require 'set' [X.new("foo"), X.new("foo")].to_set # => # class X def eql?(other) other.class == X && name.eql?(other.name ) end end [X.new("foo"), X.new("foo")].to_set # => # -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Github: http://github.com/rubyredrick Twitter: @RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale