理解Ruby Symbol

过年了还在单位,在看看ROR。简单翻译一下Knowing The Difference Between [:symbol] and [symbol:] in Rails,自己也搞搞明白。


对于Rails新手来说,看到一个冒号一会在前一会在后经常容易迷惑。那么:symbol和symbol: 的区别是什么呢?

符号前的冒号

一个前面带有冒号的符号就是一个Symbol (有点像变量)我们需要使用=>对Symbol赋值。

举个例子,如果我们想复制”Ruby on Rails”赋值给:book符号,我们就写:


:book => "Ruby on Rails"

符号后的冒号

冒号后的符号实际上和之前的是同一回事。区别在于用法,如果:symbol 使用=>赋值,而symbol: 则不需要。

我们看第一个例子,重新用符号后的冒号写一些:


book: "Ruby on Rails"

它和之前的例子相同,都是把”Ruby on Rails”赋值给:book符号。

把一个符号赋值给另一个符号

有时我们会碰到下面的例子:


book: :available

这段代码就是i讲一个变量符号赋值给另一个符号。不过千万小心类似这样的写法Book::Name,这个完全不同,Book::Name表示Name是一个模块名,Book是一个类名。


上面的文章似乎简单化了,Symbol的含义不只此。:symbol是Symbol ,看文档的说明:

Symbol对象用于表示Ruby解释器中的名字和一些字符串,他们可以采用:name和:”string”的语法格式,也可以使用to_sym方法。对于指定的名称和字符串在程序运行期间会创建相同的symbol对象。也就是说无论Fred是一个上下文中的常量、另一个中的方法,或是第三个中的类,:Fred符号在所有三个上下文中都是相同的对象。

而symbol: 则是hash中key/value的一种替换语法格式。


> x = {foo: 1, bar: 2}
=> {:foo=>1, :bar=>2}
> x[:foo]
=> 1

IBM developerWorks这篇理解 Ruby Symbol,第 1 部分 说的更细些,尤其提到使用技巧,在ruby中使用Symbol处理名字可以降低Ruby内存消耗。

典型的使用是在hash中,symbol可以作为key值,效率比使用字符串要更好,因为Ruby对每一次字符串引用都会生成一个String对象。

还有可以做hash参数,普通调用函数的时候往往需要确保参数个数、顺序匹配,而使用hash参数就没有这个问题。Ruby on Rails大量地运用了这种方式,比如:


link_to 'Show', :action => 'show', :id => product

add_column :products, :price, :decimal, 
:precision => 8, :scale => 2, :default => 0

使用hash参数,可以如下定义,前半部分为固定参数,后面是可变参数,或者全部采用hash参数。

理解 Ruby Symbol ,第 2 部分: Symbol 内幕 提到使用:Symbol的方式会创建Symbol对象,保存在符号表中,这是一个全局数据结构,存放了所有Symbol的(数字ID、名字)对,Ruby不会做删除。

文中最后有一句话:Symbol 的特点决定了它的简洁和高效。 Ruby 把它的符号表敞开了给你,在 Symbol 可以更好地发挥作用时,不要吝啬使用 Symbol 。