rails里面老看到冒号开头的变量,一直不明白,这篇文章是对他的解释,给和我一样迷惑的孩子看看 Many programmers who are new to Ruby get confused when they see Ruby symbols. A lot us came to know about Ruby language through Ruby on Rails projects. In Ruby on Rails, symbols are everywhere! So it is essential to understand the concept of symbols in Ruby. A symbol in Ruby is an instance of the class Symbol. A symbol is defined by prefixing a colon with an identifier. :name, :id, :user etc. are examples of symbols. Let us see what is there in the class Symbol. Symbol class in Ruby contains one class method all_symbols and instance methods id2name, inspect, to_i, to_int, to_s and to_sym. - all_symbols - Returns an array of all the symbols in
Ruby’s symbol table.
- id2name - Returns the string representation of the symbol - :name.id2name returns “name”.
- inspect - Returns the symbol literal
- to_i - Returns an integer unique for each symbol
- to_int - Same as to_i
- to_s- Same as id2name
- to_sym - Convert the symbol to a symbol!
Symbols are most commonly used in creating hashes. For example, consider the following hash, view plainprint? 1. h = {:name => “Jayson”, :email => “admin2@rubytips.org”}
h = {:name => “Jayson”, :email => “admin2@rubytips.org”} We could have used strings instead of symbols in this case, view plainprint? 1. h = {“name” => “Jayson”, “email” => “admin2@rubytips.org”}
h = {“name” => “Jayson”, “email” => “admin2@rubytips.org”} But the advantage in using symbols is the efficient use of memory. Maximum space taken by a symbol is never more than the space taken by an integer. This is because internally symbol is stored as an integer. In case of strings the memory space depends on the size of the string. Also whenever a string is used in the program, a new instance is created. But for symbols, same identifier points to the same memory location! This can be easily checked by running the following, view plainprint? 1. puts “name”.object_id # prints -605705088 2. puts ”name”.object_id # prints -605705108 3. puts :name.object_id # prints 34258 4. puts :name.object_id # prints 34258
puts “name”.object_id # prints -605705088 puts “name”.object_id # prints -605705108 puts :name.object_id # prints 34258 puts :name.object_id # prints 34258 The memory saved may look trivial in this case. But when a predefined hash key structure is used as parameter to a method and if the method is used many times in the program, the savings can be substantial! For example, in RoR a sample link is defined as, view plainprint? 1. <%= link_to(“Edit”, :controller => “editcontroller”, :action
=\> "edit") %\>
<%= link_to(“Edit”, :controller => “editcontroller”, :action =>
“edit”) %> The first parameter is the label used for the link and
the second parameter is a hash. The second parameter is defined as
a hash to enable dynamic parameters. Now in the implementation of
link_to method, a check is done to see if :action key exists in
the hash and then corresponding value is used. Similarly
:controller is also checked and if found is used. Hence using
hashes is a good way to implement optional parameters. In this
example we could have used “controller” and “action” strings
instead of symbols :controller and :action. But we will be missing
two important advantages - efficient memory usage and speed of
processing. In a rails application, you might be using link_to
hundreds of times. Assume that you have used it 10000 times in a
big application. If we assume every call contained :controller and
:action symbols, total memory required by the symbols = 2 * size
of an integer. Whether we call link_to once or millions of times
the memory taken remains same. But things would be different in
case of strings as keys. Whenever a link_to is called 2 new
strings “controller” and “action” will be created. Hence a total
memory allocation of 10000*16 bytes would have done by Ruby
interpreter (of course garbage collector will ensure memory usage
at any point to be much less than this). Second is the question of
speed. We know that link_to internally compares hash key to
:controller and :action. This is extremely fast since it is
equivalent to comparing integers. But if we had used strings,
comparison such as “controller”==”controller” is inefficient since
it involves comparison of all the characters in it. Strings are
scoped and they get destroyed/garbage collected when the execution
goes out of scope. But in case of symbols, they remain defined as
long as the program is running. So if you have a very large number
of symbols there could be a lot of unusable memory. It is possible
convert a string to symbol using the to_sym method. Hence
“controller”.to_sym returns :controller. Symbol identifiers can be
quoted and they can also contain special characters. Hence
:”wow, this is a symbol!” is a valid symbol. In short, symbols
are used instead of strings wherever we care only about the
identity and not the content. Why we use them? Because they are
memory efficient and comparison operation on them are really fast.
Now if you are still confused about symbols, just forget about
them. In time you will realize what they are!
This entry was posted on Saturday, January 26th, 2008 at 10:45 am
and is filed under
Ruby Tips.