img_array = [
[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 0, 1]
]
Мы имеем:
enum = img_array.each
#=> #<Enumerator: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 0, 1]]:each>
Array#each поэтому создает перечислитель, который является экземпляром класса Enumerator. Метод Enumerator#each проходит каждый элемент enum
к блоку и присваивает блок переменные:
enum.each { |row, row_index| puts "row=#{row}, row_index=#{row_index}" }
# row=0, row_index=1
# row=4, row_index=5
# row=8, row_index=9
Мы можем увидеть, что каждый из элементов enum
являются с помощью метода Enumerator#next:
enum.next #=> StopIteration: iteration reached an end
Упс! Я забыл сбросить перечислитель:
enum.rewind
#=> #<Enumerator: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 0, 1]]:each>
enum.next #=> [0, 1, 2, 3]
enum.next #=> [4, 5, 6, 7]
enum.next #=> [8, 9, 0, 1]
enum.next #=> StopIteration: iteration reached an end
В качестве альтернативы, мы могли бы преобразовать перечислитель в массив (нет необходимости rewind
):
enum.to_a #=> [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 0, 1]]
Когда элемент ([0, 1, 2, 3]
) передается к блоку, блочные переменные присваиваются следующим образом:
row, row_index = [0, 1, 2, 3] #=> [0, 1, 2, 3]
row #=> 0
row_index #=> 1
Если переменные были |row, row_index, col_index|
, назначение будет:
row, row_index, col_index = [0, 1, 2, 3] #=> [0, 1, 2, 3]
row #=> 0
row_index #=> 1
col_index #=> 2
Если бы они были |row, row_index, *rest|
, это было бы:
row, row_index, *rest = [0, 1, 2, 3] #=> [0, 1, 2, 3]
row #=> 0
row_index #=> 1
rest #=> [2, 3]
Это называется parallel (or multiple) assignment. Вы можете прочитать правила для таких назначений по ссылке, которую я дал.
Невозможно воспроизвести. Это даже не актуально. – sawa
@sawa Он отлично работает для меня в ruby-2.2.2 и дает описанный результат. –