In Ruby every object has an object_id that uniquely identifies that object in that particular instance of the Ruby process. Ruby also treats integers as objects—they are instances of
Fixnum. For efficiency reasons, though, Ruby implements integers internally as simple values. That is, it doesn’t allocate heap memory for every integer you use, it just passes the value around instead. So how does Ruby generate object ids for all these integers?
You may have never noticed, but all the object ids that you usually end up seeing are even.
irb(main):011:0> Object.object_id => 110230 irb(main):012:0> Object.new.object_id => 191490 irb(main):013:0> nil.object_id => 4 irb(main):014:0> "a_string".object_id => 177360
This is because Ruby is reserving all the odd numbers to be object_ids for
irb(main):015:0> 1.object_id => 3 irb(main):016:0> 2.object_id => 5 irb(main):017:0> 3.object_id => 7 irb(main):018:0> 4.object_id => 9
Not only are they reserved, they’re calculated using a simple formula! This allows Ruby to easily get back to the value from the id if you should ever ask for it.
irb(main):022:0> ObjectSpace._id2ref(9) => 4
And now if you ever see an odd (as in n % 2 = 1, not strange) object_id in some Ruby output somewhere, you’ll know immediately what the value of that object is!