Symbol เขียนแบบ :testing บางคนสับสนกับ variables แต่มัน คล้าย String มากกว่า
ความแตกต่าง Symbols vs Strings
Strings ใช้กับ Data (ข้อมูล) Symbols ใช้เป็น Identifiers (ตัวระบุตัวตน) นี่คือความแตกต่างหลัก Symbols ไม่ใช่แค่ string อีกประเภท มีวัตถุประสงค์ต่างกัน
When to Use Symbols (เมื่อไหร่ควรใช้ Symbols)
- แทน method และ instance variable names:
attr_reader :title(:title แทน @title) - Hash keys:
{a: 1, b: 2}(syntax sugar ของ{:a => 1})
ข้อดี: อ่านง่าย, Immutable (ไม่เปลี่ยนแปลงได้), benchmark เร็วกว่า string keys ~1.7x
:rubyguides.object_id # 437768 :rubyguides.object_id # 437768 # object_id เดียวกัน = same object
ใช้ใน metaprogramming: [1,2,3].send(:first)
สรุป: ใช้ symbols เป็น ชื่อ/ฉลาก (methods, keys) ใช้ strings เมื่อสนใจ ข้อมูล (ตัวอักษร)
Converting Between Strings & Symbols
to_s symbol → string (symbols มีเมธอดน้อยกว่า string, immutable ต้องการแก้ตัวอักษรต้องแปลง)
def method_missing(method_name, *args, &block)
if method_name.to_s[-1] == "?" # ต้องแปลงก่อนเช็คตัวอักษรสุดท้าย
# do something
else
super
end
end
to_sym string → symbol: "rubyguides".to_sym # :rubyguides
Creating An Array Of Symbols
%i(a b c) # [:a, :b, :c] ประหยัดการพิมพ์ colon และ comma คล้าย %w(a b c) สำหรับ strings
Symbol GC (Advanced)
ก่อน Ruby 2.2 symbols ไม่ถูก GC (immortal) Ruby 2.2+ มี Symbol GC:
p Symbol.all_symbols.size # 2443
('aa'..'aj').map(&:to_sym)
GC.start
p Symbol.all_symbols.size # 2453 (เพิ่ม 10 ตามที่สร้าง)
บน Ruby 2.2+ จำนวนจะเท่าเดิม (mortal symbols ถูกลบ) บาง symbols ไม่ถูกลบเลย "immortal symbols" นับได้ด้วย ObjectSpace:
require 'objspace'
ObjectSpace.count_symbols
# {:mortal_dynamic_symbol=>3, :immortal_dynamic_symbol=>5, :immortal_static_symbol=>3663, :immortal_symbol=>3668}
Mortal symbols มาจาก to_sym immortal_promoted = mortal ที่กลาย immortal (เช่นสร้าง method ชื่อ mortal symbol)
Summary
- Symbols immutable
- Symbols ไม่ใช่ pointer ไปยังค่า มันคือค่าเอง
- Strings สำหรับ data, Symbols สำหรับ identity
- แปลงระหว่าง string/symbol ด้วย to_s/to_sym
- Symbol GC ใน Ruby 2.2+ ทำความสะอาด temporary symbols