Why do two identical strings have the same objectid in Ruby?
As you know, in Ruby, two identical strings do not have the same object_id, while two are the same characters. For example:
irb(main):001:0> :george.object_id == :george.object_id
=> true
irb(main):002:0> "george".object_id == "george".object_id
=> false
However, my code below shows that two strings have the same value "one" with the same object_id.
class MyArray < Array
def ==(x)
comparison = Array.new()
x.each_with_index{|item, i| comparison.push(item.object_id.equal?(self[i].object_id))}
if comparison.include?(false) then
false
else
true
end
end
end
class MyHash < Hash
def ==(x)
y = Hash[self.sort]
puts y.class
puts y
x = Hash[x.sort]
puts x.class
puts x
puts "______"
xkeys = MyArray.new(x.keys)
puts xkeys.class
puts xkeys.to_s
puts xkeys.object_id
puts xkeys[0].class
puts xkeys[0]
puts xkeys[0].object_id
puts "______"
xvals = MyArray.new(x.values)
puts "______"
selfkeys = MyArray.new(y.keys)
puts selfkeys.class
puts selfkeys.to_s
puts selfkeys.object_id
puts selfkeys[0].class
puts selfkeys[0]
puts selfkeys[0].object_id
puts "______"
selfvals = MyArray.new(y.values)
puts xkeys.==(selfkeys)
puts xvals.==(selfvals)
end
end
a1 = MyHash[{"one" => 1, "two" => 2}]
b1 = MyHash[{"one" => 1, "two" => 2}]
puts a1.==(b1)
And get
Hash
{"one"=>1, "two"=>2}
Hash
{"one"=>1, "two"=>2}
______
MyArray
["one", "two"]
21638020
String
one
21641920
______
______
MyArray
["one", "two"]
21637580
String
one
21641920
______
true
true
As you can see from the result, 2 String objects have the same value "one" with the same object_id 21641920, whereas it is assumed to have a different ID. So can anyone give me hints or tell me how can I get different ids in this case? Regards.
source to share
When an object is String
used as a key in Hash
, the hash will duplicate and freeze the string internally and use that copy as its key.
Link: Hash#store
.
source to share
Starting with ruby ββ2.2, strings used as keys in hash literals are frozen and deduplicated: the same string will be reused.
This is a performance optimization: by not allocating many copies of the same string facility, there are fewer objects to allocate and fewer to garbage collect.
Another way to see frozen string literals in action:
"foo".freeze.object_id == "foo".freeze.object_id
Will return true in ruby ββversions> = 2.1
source to share