2011-05-12 103 views
8

注意: mischa的splat on GitHub有很多很酷的互動*的實例。Ruby中的語法[* a..b]是什麼意思?

通過google搜索,我發現有一個辦法在Ruby中的一個數字範圍的迭代(您的經典C風格的for循環)

for (i = first; i <= last; i++) { 
    whatever(i); 
} 

是做這樣的事情

[*first..last].each do |i| 
    whatever i 
end 

但是這個[*first..last]語法究竟發生了什麼?我打得四處irb,我看到:

ruby-1.9.2-p180 :001 > 0..5 
=> 0..5 
ruby-1.9.2-p180 :002 > [0..5] 
=> [0..5] 
ruby-1.9.2-p180 :003 > [*0..5] 
=> [0, 1, 2, 3, 4, 5] 
ruby-1.9.2-p180 :004 > *0..5 
SyntaxError: (irb):4: syntax error, unexpected tDOT2, expecting tCOLON2 or '[' or '.' 
*0..5 
    ^

一切我在線閱讀討論了一元星號爲擴大和摺疊傳遞給方法,可變長度參數有用的參數很有列出

def foo(*bar) 
    bar 
end 

foo 'tater' # => ["tater"] 
foo 'tater', 'tot' # => ["tater", "tot"] 

我明白了,但我不明白它是如何適用於我在上面的塊示例中進行的擴展。我知道Ruby方法是迭代數組或集合,而不是使用數組長度並迭代整數索引。然而,在這個例子中,我真的在處理一個整數列表。 :)

+1

我的整個做法可能是錯誤的。我應該只是做'(first..last)。每個...',但我仍然想知道那裏發生了什麼。:) – 2011-05-12 17:17:04

+0

也請試試:'x = * 0..5; px'和'a = [1,2,3]; b = [4,5,6]; c = [* a,* b]; pc '(Ruby 1.9+) – Phrogz 2011-05-12 17:26:58

+1

你也可以使用'first.upto(last){| i | ...}'或'first.step(last){| i | ...}(後一種方法允許你以1以外的增量步進) – Phrogz 2011-05-12 17:32:35

回答

12
[*1..10] 

是一回事

(1..10).to_a # call the "to array" method 

您創建的Array類的實例實現了Enumerable,因此您的循環可以工作。在定義to_a方法的類上,可以使用帶括號的splat運算符語法。雖然Splat做的不僅僅是打電話給#to_a,它還是值得Google自己搜索的。

現在,在你的情況下,Range類本身是已經Enumerable,所以你可能只是這樣做:

(first..last).each do |v| 
    ... 
end 
3

它被稱爲splat操作符。如果你喜歡一個參數位置或陣列的特定位置中使用它,它會擴展到它的元素:

a = [1] 
[*a, 3] # => [1, 3] 
b = [1, 2] 
[*b, 3] # => [1, 2, 3] 

你不能用它裸露或範圍:

*a..3 # => error. 
(*a..3) # => error. 

當你有東西是不是一個數組,它返回本身:

a = 1 
[*a, 3] # => [1, 3] 
3

[first..last]是隻含有1範圍對象的數組。 [*first..last]是一個包含該範圍的元素作爲參數列表發送的數組。 *在參數列表的上下文中起作用。