符號型態


你可以使用:name方式建立Symbol實例。例如
>> :a
=> :a
>> :a.class
=> Symbol
>>


Ruby以Symbol實例代表程式中使用到的符號象徵,像是變數名稱、方法名稱、類別名稱、模組名稱等,如果你使用某個物件的methods方法,可以取得Symbol實例組成的陣列。例如取得字串的方法清單:
>> "".methods
=> [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :le
ngth, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upt
o, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :to_i, :to_f, :t
o_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upca
se!, :downcase!, :capitalize!, :swapcase!, :hex, :oct, :split, :lines, :bytes, :
chars, :codepoints, :reverse, :reverse!, :concat, :<<, :crypt, :intern, :to_sym,
 :ord, :include?, :start_with?, :end_with?, :scan, :ljust, :rjust, :center, :sub
, :gsub, :chop, :chomp, :strip, :lstrip, :rstrip, :sub!, :gsub!, :chop!, :chomp!
, :strip!, :lstrip!, :rstrip!, :tr, :tr_s, :delete, :squeeze, :count, :tr!, :tr_
s!, :delete!, :squeeze!, :each_line, :each_byte, :each_char, :each_codepoint, :s
um, :slice, :slice!, :partition, :rpartition, :encoding, :force_encoding, :valid
_encoding?, :ascii_only?, :unpack, :encode, :encode!, :to_r, :to_c, :>, :>=, :<,
 :<=, :between?, :nil?, :!~, :class, :singleton_class, :clone, :dup, :initialize
_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :tr
ust, :freeze, :frozen?, :methods, :singleton_methods, :protected_methods, :priva
te_methods, :public_methods, :instance_variables, :instance_variable_get, :insta
nce_variable_set, :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?,
 :tap, :send, :public_send, :respond_to?, :respond_to_missing?, :extend, :displa
y, :method, :public_method, :define_singleton_method, :__id__, :object_id, :to_e
num, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
>>


可以使用Symbol.all_symbols取得目前程式中所有Symbol實例清單,這是一份很長的內容。例如以Ruby 1.9.2 p290,在irb中取得的清單長度是3519。

先前談過,變數名稱、方法名稱、類別名稱、模組名稱等都是一種符號象徵,當你建立了一個變數名稱、方法名稱、類別名稱、模組名稱,那麼在Symbol.all_symbols就會有個Symbol實例來代表它:
>> Symbol.all_symbols.size
=> 3519
>> abc = 10
=> 10
>> Symbol.all_symbols.size
=> 3520
>> def some; end
=> nil
>> Symbol.all_symbols.size
=> 3521
>> class Other; end
=> nil
>> Symbol.all_symbols.size
=> 3522
>>


變數名稱、方法名稱、類別名稱、模組名稱等都是一種符號象徵,都會有個Symbol實例來代表,反過來說,你也可以使用Symbol實例來代表你想表示的對象。例如想得知某個字串上是否有upcase方法,可以如下:
>> "".methods.include? :upcase
=> true
>>


例如,陣列上有個reduce方法,可以指定程式區塊,對逐一移出陣列的元素進行某些動作,第一個區塊參數是程式區塊傳回值,預設為0,每次移出陣列的值會作為第二個區塊參數。例如想要對陣列中的值加總,可以如下:
>> [1, 2, 3, 4, 5].reduce { |sum, element|
?>     sum + element
>> }
=> 15
>>


{}的區塊寫法與do..end是幾乎相同的意義,慣例中,在一行中可寫完的區塊可使用{},有傳回值的時候也可使用 {},do..end則通常用於具有邊際效應的程式區塊。

實際上,若你只是對傳入的兩個區塊參數進行相加,可以指定:+,這代表著使用+方法:
>> [1, 2, 3, 4, 5].reduce(:+)
15
>>


名稱是一種符號,字串撰寫名稱,可以使用字串的to_sym方法從字串取得Symbol實例,事實上,許多接受Symbol作為引數的方法,也接受字串:
>> "+".to_sym
=> :+
>> "+".to_sym.class
=> Symbol
>> [1, 2, 3, 4, 5].reduce("+")
=> 15
>>


許多初學者因此搞不清楚字串與Symbol的差別,正如先前所談,程式語意上,名稱只是一種符號,字串是用來撰寫名稱,如果就程式執行來說,Symbol實例是不可變動的(Immutable),而且整個程式中,Symbol實例是唯一的(Unique),但字串則沒有這兩個特性。例如:
>> x = "123"
=> "123"
>> x << "456"
=> "123456"
>> x
=> "123456"
>> "123".object_id
=> 20334732
>> "123".object_id
=> 20182656
>> :a.object_id
=> 332744
>> :a.object_id
=> 332744
>>