tags:

views:

83

answers:

3
test = 'a'
test2 = '@a'.slice(0)
test3 = '@a'[1]

puts test.hash
puts test2.hash
puts test3.hash

Output:

100
64
97

Is this a bug or am I misunderstanding how the hash method works? Is there a way to fix this?

+2  A: 

The reason is that each variable refers to different a object with its own unique hash code! The variable test is the string "a", test2 is the integer 64 (the character number of '@'), and test3 is the integer 97 ('a'). The surprise is probably that in Ruby, the elements of strings are integers, not strings or characters.

maerics
+3  A: 

The results of these expressions are not all the same data. Ruby 1.8 integers contain character numbers for single character indexing. This has been changed in Ruby 1.9, but slice(0) returns the first character of the string '@', not 'a'.

In Ruby 1.8 (using irb):

irb(main):001:0> test = 'a'
=> "a"
irb(main):002:0> test2 = '@a'.slice(0)
=> 64
irb(main):003:0> test3 = '@a'[1]
=> 97
irb(main):004:0> test.hash
=> 100
irb(main):005:0> test2.hash
=> 129
irb(main):006:0> test3.hash
=> 195

In Ruby 1.9.1:

irb(main):001:0> test = 'a'
=> "a"
irb(main):002:0> test2 = '@a'.slice(0)
=> "@"
irb(main):003:0> test3 = '@a'[1]
=> "a"
irb(main):004:0> test.hash
=> 1365935838
irb(main):005:0> test2.hash
=> 347394336
irb(main):006:0> test3.hash
=> 1365935838
Ken Bloom
+1  A: 

As maerics points out, unless you've defined your own hash method for the class you're using, the hash might simply be on the object itself, not its contents. That said, you can (and should) define your own hash method for any class where you define an equals method.

In Ruby, the String class already does this for you:

irb(main):001:0> test="a"
=> "a"
irb(main):002:0> test2="a"
=> "a"
irb(main):003:0> test.hash
=> 100
irb(main):004:0> test2.hash
=> 100
irb(main):005:0> test2[0]=test.slice(0)
=> 97
irb(main):006:0> test2
=> "a"
irb(main):007:0> test2.hash
=> 100

I haven't found an equivalent text for Ruby, but this page on Java gives an excellent algorithm for generating your own hash code that's not hard to copy for Ruby: http://www.javapractices.com/topic/TopicAction.do?Id=28

Ben Hocking