开发者

Symbols in Ruby

开发者 https://www.devze.com 2023-03-20 01:33 出处:网络
I don\'t know if I understand what a symbol is. I read the following in different places: Symbols are immutable, meaning that the content won\'t change after they are initialized. This means that th

I don't know if I understand what a symbol is. I read the following in different places:

  • Symbols are immutable, meaning that the content won't change after they are initialized. This means that the object can have many references to it since the content can't change.
  • Use Symbols for identity and strings where content matters.
  • Symbol object are only instantiated once, and开发者_开发问答 exists as long as the process runs.
  • About symbol table

I do not understand these phrases. Last, I don't understand what a symbol object is. Is :name a symbol object, or is :namejust a reference to a symbol object somewhere else?


This quote from the book 'Eloquent Ruby' helped me understand symbols, there's a whole chapter in the book dealing with strings and symbols that is also very good.

The answer is that we tend to use strings of characters in our code for two rather dif- ferent purposes: The first, and most obvious, use for strings is to hold some data that we are processing. Read in those Book objects from the database and you will very likely have your hands full of string data, things like the title of the book, the author’s name, and the actual text.

The second way that we use strings of characters is to represent things in our pro- grams, things like wanting to find all of the records in a table. The key thing about :all in our Book ActiveRecord example is that ActiveRecord can recognize it when it sees it—the code needs to know which records to return, and :all is the flag that says it should return every one. The nice thing about using something like :all for this kind of “stands for” duty is that it also makes sense to the humans: You are a lot more likely to recognize what :all means when you come across it than 0, or -1, or even (heaven forbid!) 0x29ef.

These two uses for strings of characters—for regular data processing tasks on the one hand and for internal, symbolic, marker-type jobs on the other—make very dif- ferent demands on the objects. If you are processing data, you will want to have the whole range of string manipulation tools at your fingertips: You might want the first ten characters of the title, or you might want to get its length or see whether it matches some regular expression. On the other hand, if you are using some characters to stand for something in your code, you probably are not very interested in messing with the actual characters. Instead, in this second case you just need to know whether this thing is the flag that tells you to find all the records or just the first record. Mainly, when you want some characters to stand for something, you simply need to know if this is the same as that, quickly and reliably.


Perhaps this IRB session can clear things up a little:

irb(main):001:0> "First".object_id
=> 23849064
irb(main):002:0> "First".object_id
=> 23842248
irb(main):003:0> "First".object_id
=> 23835432
irb(main):004:0> "First".object_id
=> 23828616
irb(main):005:0> :First.object_id
=> 301892
irb(main):006:0> :First.object_id
=> 301892
irb(main):007:0> :First.object_id
=> 301892
irb(main):008:0> :First.object_id
=> 301892
irb(main):009:0>

Imagine the object_id method as being similar to an object's address. As you can see, the "First" string has a different address each time ( meaning a new object gets created each time ), while the symbol doesn't change. Perhaps you could associate symbols with singletons ( as in the singleton pattern, not in a metaprogramming way ), for easier understanding.


You could regard symbols as a sort of constants, but that don't contain an actual value. In languages without symbols you might do something like this for convenience:

const BLUE = 1
const GREEN = 2

my_color = GREEN

...


if (my_color == GREEN)

In Ruby you can use symbols for this:

my_color = :green

...

if my_color == :green

It's more efficient since a symbol is just that, a symbol. It doesn't store a value or anything so you don't need to initialize them. I'm not sure how symbols are handled in the Ruby interpreter, but I don't think that's relevant for any novice ruby programmer.

A good guide can be found here: http://www.troubleshooters.com/codecorn/ruby/symbols.htm


I think symbols are best explained via use-cases.

For creating constants, they are more expressive than integers.

def rgb(color_symbol)
  return nil unless color_symbol.is_a? Symbol
  case color_symbol
  when :red;   { r: 255, g: 0, b: 0 }
  when :green; { r: 0, g: 255, b: 0 }
  when :blue;  { r: 0, g: 0, b: 255 }
  else; { r: 0, g: 0, b: 0 }
  end
end

p rgb(color_symbol= :red)

Is more readable than

def rgb(color_number)
  return nil unless color_number.is_a? Fixnum
  case color_number
  when 1; { r: 255, g: 0, b: 0 }
  when 2; { r: 0, g: 255, b: 0 }
  when 3; { r: 0, g: 0, b: 255 }
  else; { r: 0, g: 0, b: 0 }
  end
end

p rgb(color_number= 2)

For comparisons in conditional statements, symbols are just compared via their unique address, so they are more efficient than strings, which are compared by length and then every character.

def rgb(color_string)
  return nil unless color_string.is_a? String
  case color_string
  when "red";   { r: 255, g: 0, b: 0 }
  when "green"; { r: 0, g: 255, b: 0 }
  when "blue";  { r: 0, g: 0, b: 255 }
  else; { r: 0, g: 0, b: 0 }
  end
end

p rgb(color_string= "blue")

This is going to be less efficient than using symbols.


This article can be also of interest http://www.robertsosinski.com/2009/01/11/the-difference-between-ruby-symbols-and-strings/ as it helped me to understand how symbols differ from strings.


A Symbol instance is an ordered set of characters. A String instance is a container for characters, a place that can contain any sequence of characters.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号