From: Rick DeNatale Date: 2009-09-04T01:37:21+09:00 Subject: Re: doubling numbers with Object#object_id On Thu, Sep 3, 2009 at 11:54 AM, Charles Oliver Nutter wrote: > On Wed, Aug 26, 2009 at 5:21 PM, Shot (Piotr Szotkowski) wrote: >> EbFFA: >> >>> I was playing with Ruby and wrote an interesting method: >> >>>     def double n >>>       n.object_id - 1 >>>     end >> >>> Anyone know why this works? Why Ruby was implemented this way? >> >> Note that other Ruby implementations (JRuby, Rubinius, IronRuby…) do >> not have to keep this contract; it’s best considered as MRI peculiarity. >> But yes, I do find this design beautiful – as well as Ruby’s method >> lookup: http://www.viddler.com/explore/CobyR/videos/1/ > > I don't know that it's particularly beautiful; it's just a side effect > of Fixnums not having any internal state and not actually being > objects in MRI. Because they are "immediates" they don't actually have > an object_id. As a result, their object_id is just based on their > actual value, 2n+1. All other objects then get stuffed into the > remaining even object_ids, and fixnum.object_id - 1 == fixnum * 2. And its not that particularly unique to MRI. I know lots of VM implementations for various languages (Ruby, Smalltalk, JavaScript ...) which use different variations of representing an integer n smaller than 2**b for some b less than the word length as: n * 2**flag_shift + int_flag where flag_shift is some small integer (usually but not always 1) and int_flag is usually 1 or at least odd, since on most machines a pointer to an object will be aligned on some even address boundary. For some reason, Googles V8 JavaScript VM uses an int_flag of 1 and SETs the low order bit of references which are pointers, at least according to a video I watched about the implementation. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale