11
votes

When I first started reading about and learning ruby, I read something about the power of ruby symbols over strings: symbols are stored in memory only once, while strings are stored in memory once per string, even if they are the same.

For instance: Rails' params Hash in the Controller has a bunch of keys as symbols:

params[:id] or
params[:title]...

But other decently sized projects such as Sinatra and Jekyll don't do that:

Jekyll:

post.data["title"] or
post.data["tags"]...

Sinatra:

params["id"] or
params["title"]...

This makes reading new code a little tricky, and makes it hard to transfer code around and to figure out why using symbols isn't working. There are many more examples of this and it's kind of confusing. Should we or shouldn't we be using symbols in this case? What are the advantages of symbols and should we be using them here?

4

4 Answers

4
votes

In ruby, after creating the AST, each symbol is represented as a unique integer. Having symbols as hash keys makes the computing a lot faster, as the main operation is comparison.

4
votes

Symbols are not garbage collected AFAIK, so that might be a thing to watch out for, but except for that they really are great as hash keys.

0
votes

One reason for the usage of strings may be the usage of yaml to define the values.

require 'yaml'
data = YAML.load(<<-data
    one:
      title: one
      tag: 1
    two:
      title: two
      tag: 2
  data
  )  #-> {"one"=>{"title"=>"one", "tag"=>1}, "two"=>{"title"=>"two", "tag"=>2}}

You may use yaml to define symbol-keys:

require 'yaml'
data = YAML.load(<<-data
    :one:
      :title: one
      :tag: 1
    :two:
      :title: two
      :tag: 2
  data
  ) #-> {:one=>{:title=>"one", :tag=>1}, :two=>{:title=>"two", :tag=>2}}

But in the yaml-definition symbols look a bit strange, strings looks more natural.

Another reason for strings as keys: Depending on the use case, it can be reasonable to sort by keys, but you can't sort symbols (at least not without a conversion to strings).

-1
votes

The main difference is that multiple symbols representing a single value are identical whereas this is not true with strings. For example:

irb(main):007:0> :test.object_id
=> 83618
irb(main):008:0> :test.object_id
=> 83618
irb(main):009:0> :test.object_id
=> 83618

3 references to the symbol :test, all the same object.

irb(main):010:0> "test".object_id
=> -605770378
irb(main):011:0> "test".object_id
=> -605779298
irb(main):012:0> "test".object_id
=> -605784948

3 references to the string "test", all different objects.

This means that using symbols can potentially save a good bit of memory depending on the application. It is also faster to compare symbols for equality since they are the same object, comparing identical strings is much slower since the string values need to be compared instead of just the object ids.

I usually use strings for almost everything except things like hash keys where I really want a unique identifier, not a string