Ruby Splat(*)符號使用
*符號英文稱為Asterisk或Splat,中文尚未看到統一稱呼,一般是稱為乘號或星號。一般常見於乘法,但在乘法用途中,是當做雙元運算子。當用作單元運算子的時候,他會有非常豐富多元的用途。
多個變數轉換為數列
*用於單元運算子,第一種用法是將一串變數轉換為數列:
*a = 1,2,3
# a = [1,2,3]
反過來,也可以將數列轉換為一串變數,並帶入method中使用:
def sum(*args)
puts args.inject(:+)
end
sum(1,2,3)
# => 6
也可以先指定第一個變數為主要用途,再帶入剩餘的變數:
def say(person, *words)
words.each { |w| puts person + ": " + w }
end
say("John", "Hello", "My name is john", "I am 30 years old")
# => John: Hello
# => John: My name is john
# => John: I am 30 years old
利用*符號,可以讓一個method帶入多個變數而不會出現Wrong number of argument的錯誤。
同樣的方法可以交換順序使用,把數列放在最前面,而最後面是固定使用的變數:
def say(*words, person)
words.each { |w| puts person + ": " + w }
end
say("Hello", "My name is john", "I am 30 years old", "John")
# => John: Hello
# => John: My name is john
# => John: I am 30 years old
看得出來嗎?整個功能與上個例子的相同,只有帶入的順序不同。另外,splat符號也可以將數列切成一串的變數帶入method中,以上方的say method為例:
sentences = ["Hello", "Nice to meet you", "How are you?"]
say("Nancy", *sentences)
# => Nancy: Hello
# => Nancy: Nice to meet you
# => Nancy: How are you?
這樣一來,就可以利用splat將數列整個帶入method當中,不需再多做處理。
多重指定變數Parallel Assignment
大家應該都知道Ruby當中可以在同一行指定變數:
a,b = "hello ", "world"
puts a + b
# => hello world
而使用splat符號,可以大幅增加指定變數的空間:
first, *all = [1,2,3,4,5]
# first = 1
# all = [2,3,4,5]
*all, last = [1,2,3,4,5]
# all = 1,2,3,4
# last = 5
first, *all, last = [1,2,3,4,5]
# first = 1
# all = [2,3,4]
# last = 5
其他用法
還有一個奇妙用法,就是用來避開method的錯誤訊息。設定如果帶入太多參數,其他不用的就捨棄:
def plus(a, b, *)
puts a + b
end
plus(1, 2, 3, 4, 5)
# => 3
上述例子中,只有1和2有實際帶入method中計算,不過這種防呆機制不易察覺有bug,無法及時補救,不建議使用。