语法[* a..b]在Ruby中意味着什么?

时间:2011-05-12 17:12:57

标签: ruby syntax operators splat

注意: mischa的splat on GitHub有许多很酷的交互式示例*

通过谷歌搜索,我发现了一种迭代Ruby中一系列数字的方法(经典的C风格循环)

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 Way是迭代数组或集合,而不是使用数组长度并使用整数索引进行迭代。但是,在这个例子中,我真的在处理一个整数列表。 :)

3 个答案:

答案 0 :(得分:12)

[*1..10]

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

您创建的Array类的实例实现了Enumerable,因此您的循环可以正常工作。在定义to_a方法的类上,您可以使用带括号的 splat运算符语法。 Splat做的不仅仅是调用#to_a,而且值得谷歌搜索。

现在,在您的情况下,Range类本身已经一个Enumerable,所以您可以这样做:

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

答案 1 :(得分: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]

答案 2 :(得分:3)

[first..last]是一个只包含1个范围对象的数组。 [*first..last]是一个数组,包含作为参数列表发送的该范围的元素。 *在参数列表的上下文中工作。