Ruby adds `Symbol#name` to return frozen string corresponding to the symbol name


Ruby adds instance method #name to Symbol.

This method returns an instance of String with the same underlying value as the instance of Symbol:

  :test.name
=> "test"

The resultant string is frozen.

irb(main):002:0> :laptop.name
=> "laptop"
irb(main):003:0> :laptop.name.object_id
=> 180
irb(main):004:0> :laptop.name.object_id
=> 180
irb(main):005:0> :laptop.name.frozen?
=> true

In the above example, we could observe that the same object_id is being returned for different invocations of :laptop.name. It indicates that no new instances of String are allocated after the first allocation of “laptop”.

How is it different from #to_s on Symbol?

When we call #to_s on a symbol, the resulting string is not frozen.

A new instance of String will be allocated when #to_s is again called on the same instance of Symbol.

irb(main):003:0> :laptop.to_s
=> "laptop"
irb(main):004:0> :laptop.to_s.object_id
=> 200
irb(main):005:0> :laptop.to_s.object_id
=> 220

In the above example, we could see that a different instance of String is allocated whenever #to_s is called on :laptop.

Where can we use this?

If the piece of code which calls #to_s on a symbol lies in a hotspot of our application, it will result in creating lots of instances of String and they need to be eventually garbage collected, resulting in additional GC efforts.

Instead, we can call #name on a symbol to obtain a frozen instance of String.

The resulting frozen string will be re-used on subsequent invocations of #name on the same instance of Symbol. Hence, it won’t be an overhead to the Garbage Collector.

History

A proposal was made to request a frozen instance of String by calling #to_s on Symbol some time back.

The same was implemented as an experimental feature in ruby 2.7.

Unfortunately, it had to be reverted due to some backward compatibility issues.