前言
Symbol 符號在Ruby裡,常見以冒號配文字的形式出現 (譬如是 :user or :title)。
乍看之下,不就是 冒號 + 變數 或是 冒號 + 字串 嗎?
就是因為外表上蠻相似的,因此容易與”變數”及”字串”混淆。對新手而言,搞懂symbol及正確的使用符號是有難度的。
在這裡我就嘗試說明在Ruby 世界裡的符號(Symbol)是什麼?它跟字串又有何不同? 首先我們先了解在Ruby的世界裡每一個變數、文字、數字都是物件,而symbol也是如此。
“Symbol 其實是有點玄的東西,有些人認為它就是的變數,或就是只是個名字,但事實上它不就是變數或名字這麼簡單,你可以想像它是一個「帶有名字的物件」”- 五倍紅寶石學院 -
Symbol VS 字串 VS 變數
換句話說,數字5也是物件(數字物件),文字”hello”(字串物件),而符號 :name則是(符號物件)。 從另一個角度來看,把”符號”看作值(value)就會容易理解許多。
舉例來說,我們會把“變數”=“值”( age = 29),但是不會把”值”指定給”值”(13=25),因為這是很明顯的錯誤。所以符號不能指定給值(:age=29)因為符號就是屬於值。
2.6.3 :007 > :age = 29
Traceback (most recent call last):
SyntaxError((irb):7: syntax error, unexpected '=', expecting end-of-input)
字串也是如此,當理解(29 = “Rex”)是錯誤的時候,就不難看出(:name = “Rex”)也是錯誤的了。
Symbol 效能 ??
2.6.3 :001 > "rex".object_id
=> 70167057786220
2.6.3 :002 > "rex".object_id
=> 70167057770160
2.6.3 :003 > "rex".object_id
=> 70167069560160
2.6.3 :004 >
從上面的程式碼看出,每一次呼叫 “rex” 字串都會跟 Ruby 要一個新的 object id,也就是說都不會存在同一個記憶體裡。
2.6.3 :004 > :rex.object_id
=> 1509788
2.6.3 :005 > :rex.object_id
=> 1509788
2.6.3 :006 > :rex.object_id
=> 1509788
2.6.3 :007 >
然而只要是一樣的symbol,就會有相同的 object id。例如:上面的程式碼可看出 :rex 符號都是擁有相同的 object_id => 1509788
Symbol有相同的object_id,表示他們是同一顆東西,當 Ruby 需要重複存取符號時,就不需要重新產生新的記憶體,效能上也會相對的好一些。
另一個不同之處,就是字串的內容可以修改,但是符號不行。我們可以用存取陣列的方式修改字串,但是符號是無法經由任何方法改變的。因為即使是一個字元的改變(打錯字)就會變成是不同的符號了。
2.6.3 :001 > name = "Kevin"
=> "Kevin"
2.6.3 :002 > name[1] = "C"
=> "C"
2.6.3 :003 > puts name
KCvin
在這裡我們把陣列裡 index=1的字 ‘e’ 更換為 ‘C’,這樣是沒問題的! 但是符號的話會是什麼情況呢?
2.6.3 :004 > :name = "Kevin"
Traceback (most recent call last):
3: from /Users/kevin/.rvm/rubies/ruby-2.6.3/bin/irb:23:in
2: from /Users/kevin/.rvm/rubies/ruby-2.6.3/bin/irb:23:in `load'
1: from /Users/kevin/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in
SyntaxError ((irb):4: syntax error, unexpected '=', expecting end-of-input)
:name = "Kevin"
跟之前的例子一樣,符號是值,所以不可以把值 “Kevin” 字串指定給另一個值
Comments