weefwefwqg3
weefwefwqg3

Reputation: 1001

why 2 same strings have the same object_id in Ruby?

As you may know that in Ruby two same strings do not have a same object_id, while two same symbols do. For instance:

irb(main):001:0> :george.object_id == :george.object_id
=> true
irb(main):002:0> "george".object_id == "george".object_id
=> false

However, in my code below, it shows that two strings which have a same value "one" having a 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 that 2 String objects with have a same value "one" having a same object_id 21641920, while it's supposed to have different ID. So can anyone give me some hints or tell me how can I get different ID in this case? Best Regards.

Upvotes: 3

Views: 1181

Answers (2)

Frederick Cheung
Frederick Cheung

Reputation: 84182

As of ruby 2.2 strings used as keys in hash literals are frozen and de-duplicated: the same string will be reused.

This is a performance optimisation: not allocating many copies of the same string means 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 versions of ruby >= 2.1

Upvotes: 2

Yu Hao
Yu Hao

Reputation: 122493

When a String object is used as a key in a Hash, the hash will duplicate and freeze the string internally and will use that copy as its key.

Reference: Hash#store.

Upvotes: 6

Related Questions