I first ran the below Part I of code and get the desired output, now just to play around it and to do some research I did Part II.
Part I
irb(main):001:0> h1 = { "a" => 100, "b" => 200, :c => "c" }
=> {"a"=>100, "b"=>200, :c=>"c"}
irb(main):002:0> h1["a"]
=> 100
irb(main):002:0> h1[:c]
=> "c"
Part II
irb(main):003:0> h1.compare_by_identity
=> {"a"=>100, "b"=>200, :c=>"c"}
irb(main):004:0> h1.compare_by_identity?
=> true
irb(main):005:0> h1["a"]
=> nil
irb(main):006:0> h1[:c]
=> "c"
irb(main):007:0>
How does h1["a"]
give different values in Part I and Part II but not the same happened with h1[:c]
?
I’m using Ruby 1.9.3.
The docs for
compare_by_identity
say this:Normally, hash keys will be matched using
eql?
, butcompare_by_identity
will instead match them usingequal?
(which is roughly equivalent to comparingobject_id
s*). Since different instances of a string with the same value have differentobject_id
s, it doesn’t match. However, symbols always have the sameobject_id
, so it does continue to match.As you can see, the
object_id
s for the strings do not match theobject_id
s of the keys in the hash, but the symbol does. In fact, if you run'a'.object_id
&'b'.object_id
(or callobject_id
on any string) repeatedly, you will get a different value each time.*The caveat here is that one could override
object_id
, but it will have no effect on the comparison sinceequal?
doesn’t actually useobject_id
. Further, redefiningequal?
will change this, but doing so is not recommended explicitly in the Ruby docs.