I
Intransition
Are there any good tutorials out there for writing proper #hash
methods?
methods?
http://en.wikipedia.org/wiki/Hash_function
in most cases it's the easiest to delegate the hash method to something
else. Example:
class X
=A0 def initialize(name)
=A0 =A0 @name =3D name
=A0 end
=A0 def hash
=A0 =A0 @name.hash
=A0 end
end
h =3D { X.new("foo") =3D> "bar" }
h[X.new("foo")] =3D "baz" # will overwrite the above
http://en.wikipedia.org/wiki/Hash_function
in most cases it's the easiest to delegate the hash method to something
else. Example:
class X
=A0 def initialize(name)
=A0 =A0 @name =3D name
=A0 end
=A0 def hash
=A0 =A0 @name.hash
=A0 end
end
h =3D { X.new("foo") =3D> "bar" }
h[X.new("foo")] =3D "baz" # will overwrite the above
And so will `h['foo'] =3D 'baz'`.
The reason is that the value of #hash is not the only thing needed to
distinguish hash keys. All objects with the same hash value are mapped
to the same hash 'bucket' hash collisions are resolved by using the
eql? method,
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.
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. =A0The ke= y
point - and I believe this is what you want to stress - is _how_ values a= re
derived. =A0The methodology applied should strive to yield different hash
values for things that are considered non equivalent. =A0For example, has= h
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 o= nly
differ in ordering. =A0We can see that Array#hash obeys this:
irb(main):001:0> [1,2].hash
=3D> 11
irb(main):002:0> [2,1].hash
=3D> 1
On the other hand, since Set conceptually is agnostic of position differe= nt
ordering of elements should not create different hash codes:
irb(main):001:0> require 'set'
=3D> true
irb(main):002:0> s1 =3D [1,2].to_set
=3D> #<Set: {1, 2}>
irb(main):003:0> s2 =3D [2,1].to_set
=3D> #<Set: {2, 1}>
irb(main):004:0> s1.hash
=3D> 14
irb(main):005:0> s2.hash
=3D> 14
irb(main):006:0> s1 =3D=3D s2
=3D> true
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
=> #<Set: {1, 2}>
irb(main):003:0> s2 = [2,1].to_set
=> #<Set: {2, 1}>
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?
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.