Что означает синтаксис [* a..b] в Ruby? - PullRequest
8 голосов
/ 12 мая 2011

ПРИМЕЧАНИЕ: Миша Сплат на 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 ]

12 голосов
/ 12 мая 2011
[*1..10]

- это то же самое, что и

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

Экземпляры класса Array, который вы создали, реализуют Enumerable, поэтому ваш цикл работает.В классах, определяющих метод to_a, вы можете использовать синтаксис оператора со скобками.Splat делает гораздо больше, чем просто вызывает #to_a, и будет стоить поиска в Google самостоятельно.

Теперь, в вашем случае, сам класс Range равен уже Enumerable, чтобы вы могли просто сделать:

(first..last).each do |v| 
  ...
end
3 голосов
/ 12 мая 2011

[first..last] - массив, содержащий только 1 объект диапазона.[*first..last] - это массив, содержащий элементы этого диапазона, отправленные в виде списка аргументов.* работает в контексте списка аргументов.

3 голосов
/ 12 мая 2011

Это называется оператором сплат.Если вы используете его в определенных позициях, таких как позиция аргумента или массив, он расширится до его элементов:

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]
...