In Ruby, Why Does Inspect() Print Out Some Kind of Object Id Which Is Different from What Object_Id() Gives

In Ruby, why does inspect() print out some kind of object id which is different from what object_id() gives?

The default implementation of inspect calls the default implementation of to_s, which just shows the hexadecimal value of the object directly, as seen in the Object#to_s docs (click on the method description to reveal the source).

Meanwhile the comments in the C source underlying the implementation of object_id shows that there are different “namespaces” for Ruby values and object ids, depending on the type of the object (e.g. the lowest bit seems to be zero for all but Fixnums). You can see that in Object#object_id docs (click to reveal the source).

From there we can see that in the “object id space” (returned by object_id) the ids of objects start from the second bit on the right (with the first bit being zero), but in “value space” (used by inspect) they start from the third bit on the right (with the first two bits zero). So, to convert the values from the “object id space” to the “value space”, we can shift the object_id to the left by one bit and get the same result that is shown by inspect:

> '%x' % (36971870 << 1)
=> "4684abc"

> a = Foo.new
=> #<Foo:0x5cfe4>
> '%x' % (a.object_id << 1)
=> "5cfe4"

Ruby object to_s what is the encoding of the object id?

Think of the object_id, or __id__ as the "pointer" for the object. It is not technically a pointer, but does contain a unique value that can be used to retrieve the internal C VALUE.

There are patterns to the value it has for some data types, as you can see with its hexadecimal representation with to_s. I am will not go into all the details, as there are already numerous answers on SO explaining, and already linked from comments, but integers (up to a FIXNUM_MAX, have predictable values, and special constants like true, false, and nil will always have the same object_id in every run.

To put simply, it is nothing more than a number, and shown as a hexadecimal (base 16) value, not any actual "encoding" or cypher.

Going to expand upon this a bit more in light of your latest edits to the question. As you posted, the hexadecimal number you see in to_s is the value of the internal C VALUE of the object. VALUE is a C data type (unsigned, pointer size number) that every Ruby object is represented as in C code. As @Stefan pointed out in a comment, for non-integer types (I speak only for MRI version), it is twice the value of the object_id. Not that you probably care, but you can shift the bits of an integer to predict the value for those.

Therefore, using you example.

A value of 0x00007fac5eb6afc8 is simple hexadecimal notation for a number. It uses a base 16 counting system as opposed to the base 10 decimal system we are more used to in everyday life. It is simply a different way of looking at the same number.

So, using that logic.

a = 0x00007fac5eb6afc8
#=> 140378300133320 # Decimal representation

a /= 2 # Remember, non-integers are half of this value
#=> 70189150066660 # Your object_id

Why getting error: Object#id will be deprecated; use Object#object_id

I believe you may have a bug in your code, which is why that warning is thrown. Object#id is most often invoked when you are inadvertently calling id on an object you weren't expecting, like nil:

>> nil.id
(irb):1: warning: Object#id will be deprecated; use Object#object_id
=> 4

If the object has an id method, a warning is not thrown. So, assuming it works locally (and this SOAP object does have an id method), the only way you should be getting this warning is if it is a different kind of object.

Thus, are you absolutely sure the object you expected is being returned? Try adding:

logger.info ">>> SOAP OBJECT: " + object.inspect

Or add some explicit error handling / object checking:

unless object.is_a?(SOAP::Mapping::Object)
raise ArgumentError, "did not get SOAP object"
end

At least then you will know something has gone wrong.

JavaScript Object Id

No, objects don't have a built in identifier, though you can add one by modifying the object prototype. Here's an example of how you might do that:

(function() {
var id = 0;

function generateId() { return id++; };

Object.prototype.id = function() {
var newId = generateId();

this.id = function() { return newId; };

return newId;
};
})();

That said, in general modifying the object prototype is considered very bad practice. I would instead recommend that you manually assign an id to objects as needed or use a touch function as others have suggested.



Related Topics



Leave a reply



Submit