Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do Ruby symbols exist because strings are mutable and not interned?

Tags:

ruby

I've been with Ruby for about a year now and have a language question: are symbols necessary because Ruby strings are mutable and not interned?

In, say, Java, strings are immutable and interned. So "foo" is always equal to "foo" in value and reference and its value cannot change. In Ruby, strings are mutable and not interned, so "a".object_id == "a".object_id will be false.

If Ruby had implemented strings like Java, symbols wouldn't be necessary, right?

like image 999
Steve Potter Avatar asked Dec 10 '22 11:12

Steve Potter


1 Answers

As of Ruby 2.3 immutable Strings have been implemented optionally via the RUBYOPT flag --enable-frozen-string-literals i.e.

RUBYOPT=--enable-frozen-string-literals ruby /some/file

This will cause all String literals (strings created using "", %q{}, %Q{}, or "#{}" styles) to become immutable. This feature is currently being considered as default for Ruby 3.0. Follow along with Feature#11473. This feature is also available on a file level rather than a global level as a "magic comment"

# frozen_string_literal: true

This will have the same impact as the RUBYOPT version but will apply only to the specific file. (one other way is to interact with the VM directly RubyVM::InstructionSequence.compile_option = {frozen_string_literal: true})

Since this is optional obviously it can be turned on and off and will still be an option in 3.0 just defaulting to on instead of off. Mutable Strings can still be created using String.new and Immutable Strings can be duped to make their dup counter part mutable. (Please Note above: interpolation "#{}" creates a new Immutable string as well because of "")

All that being said it does not replace the need for Symbols in ruby. First of all the underlying C that powers ruby leverages Symbols heavily via rb_itern to handle references for things like method definitions (These have been titled "Immortal Symbols" and will never be GCed).

Additionally Symbols like all things in ruby are their own Object and have their own useful sets of functionality. Take Symbol#to_proc for example. This originated as a monkey patch solution for syntactical ease and was consumed into core in 1.8.7. This style is highly encouraged and regularly leveraged by the ruby community as a whole. Please advise how you would suggest having degradation of this feature work with a String instead of a Symbol.

While Symbols used to be considered somewhat "dangerous" (for lack of a better word) due to their internment and memory consumption in combination with the dynamics of ruby. As of Ruby 2.2 most Symbols (see above) can be garbage collected i.e. symbols created inside of ruby through String internment (#intern, #to_sym, etc.). (These have been coined "Mortal Symbols")

Minor caveats include things like

 define_method(param[:meth].to_sym) {}

This seems like since it is calling to_sym that it should be a "Mortal Symbol" but since define_method calls rb_intern to keep the method reference it actually will create an "Immortal Symbol"

Hopefully this run down helps explain the necessity of Symbol in ruby not only from a developer standpoint but also the heavy usage as part of the C internals of ruby's implementation.

like image 174
engineersmnky Avatar answered Apr 12 '23 22:04

engineersmnky