What is a Symbol
Ruby is a powerful object-oriented scripting language (Ruby version used in this article for 1.8.6), Medium Symbol in Ruby that "name", such as the string name, identifier name.
Create a Symbol object is in front of the name or string to add a colon:
创建 symbol 对象
:foo
:test
:”abc”
:”I am a boy”
You might ask, string is the string, why there is a string name? This is because of the string in Ruby is an object, that is, String object. Regardless of their structure or operation and Symbol objects are different.
In Ruby every object has a unique object identifier (Object Identifier), can object_id Ways to get an object identifier. We take a look at the Symbol object and String object differences:
Ruby 对象标识符
irb(main):001:0> puts :foo.object_id
327458
=> nil
irb(main):002:0> puts :foo.object_id
327458
=> nil
irb(main):003:0> puts :"foo".object_id
327458
=> nil
irb(main):004:0> puts "foo".object_id
24303850
=> nil
irb(main):005:0> puts "foo".object_id
24300010
=> nil
irb(main):006:0> puts "foo".object_id
24296170
=> nil
Can see that the first three lines of the statement: foo (or: "foo") are the same Symbol object, the object id for the 327,458, then three lines of the string "foo" is different from the object, its object id followed by 24303850,24300010,24296170.
Can be seen, each String object is different, even if they contain the same string content; Symbol object for a name (string content) only to identify a Symbol object.
It is worth noting that the creation of Symbol string object should not contain '\ 0' character, while the String object is possible.
非法 Symbol 字符串
irb(main):001:0> :"fo\0o"
SyntaxError: compile error
(irb):1: symbol cannot contain '\0'
from (irb):1
irb(main):002:0> :"foo\0"
SyntaxError: compile error
(irb):2: symbol cannot contain '\0'
from (irb):2
irb(main):003:0> puts "foo\0".object_id
24305140
=> nil
irb(main):004:0> puts "fo\0o".object_id
24301000
=> nil
irb(main):005:0>
Can be used apart from a general string, you can also use operator (eg +, -, *, /), variables, constants, methods and even the names of categories to create a Symbol object, such as: + is a legitimate Symbol. In fact, in the Ruby internal operator, variables such as the name itself as a Symbol of treatment, such as when you define an instance variable, Ruby will automatically create a Symbol object, such as @ test corresponds to: @ test.
实例变量的 Symbol
class Test
attr_accessor :test
end
This class defines a method to read and write instance variables @ test. Ruby in fact created two Symbol, are examples of a variable symbol: @ test, the other is: test. That if you use the string object "test" as a parameter does? Can still be to create two symbol,: test and: @ test, why will create: test it? This is the implementation and Ruby related (at least this is the case in Ruby1.8.6).
Note that type variables @ @ test and the instance variable @ test corresponding Symbol is obviously different. Remember: the name of the same, the same Symbol.
The same name, Symbol same
class Test
puts :Test.object_id
Test = 10
puts :Test.object_id
def Test
puts :Test.object_id
end
end
Test.new.Test
运行结果
224298
224298
224298
名字不同, Symbol 不同
class Test
puts :Test.object_id
@@test = 10
puts :@@test.object_id
def test
puts :test.object_id
@test = 10
puts :@test.object_id
end
end
t =Test.new
t.test
运行结果
224298
288068
79858
288108
The first example, the class name, method name and constant name is Test, so the corresponding Symbol objects are: Test. Do not worry, Ruby can be different to distinguish it in the context of what in the end said. Of course, this is not a good programming style, but for understanding the Symbol or Ruby helpful: Symbol express a name, nothing more.
Once the definition of Symbol object will always exist until the program quit. Symbol of all Ruby objects stored in the internal symbol table, you can get through the class method Symbol.all_symbols current Ruby procedures defined in all the Symbol object, the method returns a Symbol object array. Symbol comparison because of many, you can dump to a file to view.
all_symbols 方法
irb(main):001:0> Symbol.all_symbols.size
=> 4047
irb(main):002:0> Symbol.all_symbols[0..9]
=> [:@level_notifier, :ppx, :msg_dn, :version, :secs, :@user, :pos, :socketpair,
:TkENSURE, :HTTPAccepted]
irb(main):003:0> File.open("sym", "w") do |file| file.puts Symbol.all_symbols end
=> nil
Symbol and String
Symbol objects and String objects are completely different things, a very specific object identifier illustrates this point. In addition, we can from the two methods to distinguish between objects.
See Ruby library reference, you will find String category have very many ways, including the Mixed-in method (Ruby in a class through the include other modules have been ways to achieve the effect of multiple inheritance), class methods and instance methods; and Symbol category there is only one class method all_symbols and 7 Ways examples.
For example, by [] = method to change the content of string, and the symbol will not work:
[]= 方法比较
irb(main):001:0> s="test"
=> "test"
irb(main):002:0> s[0]='1'
=> "1"
irb(main):003:0> puts s
1est
=> nil
irb(main):004:0> sym=:test
=> :test
irb(main):005:0> sym[0]=1
NoMethodError: undefined method `[]=' for :test:Symbol
from (irb):5
irb(main):006:0>
Although the Symbol and String objects are different, but between them a very close relationship. Ruby provides a method to switch between Symbol and String.
Symbol into String
To_s or use id2name Ways to Symbol into a String object:
Symbol 到 String
irb(main):001:0> :test.id2name
=> "test"
irb(main):002:0> :test.to_s
=> "test"
irb(main):003:0> :"I am a boy".to_s
=> "I am a boy"
Note that each String object is unique, and therefore call for a Symbol will produce many times more than String objects.
String into a Symbol
Except in the string preceding the colon, you can also use to_sym or intern method String into Symbol, if the Symbol already exists, then directly back.
String 到 Symbol
irb(main):001:0> var1 = "test".to_sym
=> :test
irb(main):002:0> var2 = "test".intern
=> :test
irb(main):003:0> var1 == var2
=> true
irb(main):004:0>
The use of Symbol
As mentioned in the front, Ruby has been in the use of internal Symbol, such as Ruby procedures of the various names, Symbol is essentially a symbol table in Ruby things. Deal with the use of Symbol names can reduce the Ruby memory consumption, improve speed of execution, which the next article we will see.
Symbol for us then what is the use? Of course memory. String to use the overhead is too great, because every object is a String. Think about examples of the front, a string Ruby will occur once each to create a String object.
Normally, when you face the choice of String or a Symbol, you can refer to the following standards:
If you use the contents of the string, the content may change, the use of String
If you use a fixed name or the identifier, the use of Symbol
Well, when we used names? Will be a lot of time, such as the enumerated value, keyword (Hashtable keywords, methods, parameters) and so on
As a hash table of key
Symbol hash table are the most widely used place.
In ruby, the hash and the array is similar to a hash table is a series of key / value pair collection, but its key values of wide-ranging, can be any object, such as regular expressions. But usually we will get a meaningful key, such as String, Symbol.
Hash table express the following cities classified by a collection of some machines.
Example of a hash table
hosts (
'beijing' => 'machine1',
'shanghai' => 'machine2',
'guangzhou' => 'machine3',
'tianjin' => 'machine4',
'shenzhen' => 'machine5'
)
Beijing If you want to invoke the machinery, the use of hosts [ 'beijing']. However, if we process frequently invoked to hash table value, so as not good, because Ruby on every quoted string will generate a String object, the accumulated costs are considerable.
We can use the Symbol, because of these key terms, we used that name only, such as the following hosts [: beijing]
Use Symbol as a key
hosts = {
:beijing => 'machine1',
:shanghai => 'machine2',
:guangzhou => 'machine3',
:tianjin => 'machine4',
:shenzhen => 'machine5'
}
Parameters Hash
Normally, we define the parameters of a function of the number and sequence of Writing are dead, call the function of time to ensure that the number of parameters, sequence matching, sometimes not so convenient, the use of hash parameters can solve the problem.
ROR on substantial use of this way, maybe you have seen everywhere and hash Symbol. For instance:
The use of hash parameters of method calls
link_to 'Show', :action => 'show', :id => product add_column :products, :price, :decimal, :precision => 8, :scale => 2, :default => 0
The use of hash parameters can be defined as follows, the first half of the fixed parameters, the back for the variable parameters, or simply the use of hash-wide parameters:
Parameters Hash
def my_method(para1, …, options={})
#your code
end
def my_method(options={})
#your code
end
If you wish to set some default parameters, and allow the caller to change these parameters, you can use the hash object merge! Ways
hsh.merge! (other_hash). The method will be added to HSH other_hash in content, if other_hash with HSH has duplicate key, then key in other_hash coverage HSH value of the corresponding key of the value.
Ways definition - using the default parameters
class Test
def my_method(opts={})
default_opts={:arg1 => 10, :arg2 => "abc"}
default_opts.merge!(opts)
default_opts.each{|key,value| puts "#{key} is #{value}"}
end
end
t = Test.new
t.my_method :arg1=>5, :arg3=>"def"
运行结果
arg1 is 5
arg2 is abc
arg3 is def
In Rails, the type of hash expanded, you can use reverse_merge! Ways to achieve this effect. The method in ActiveSupport:: CoreExtensions:: Hash:: ReverseMerge defined. Rails even provided assert_valid_keys method of transmission of incoming hash table of keys to the legality of testing.
Perl said that every road leads to Rome. In Ruby also like that, maybe you will find a better application of Symbol and the Hash method.







