#ruby #arrays #slice #parallel-assignment
#ruby #массивы #фрагмент #параллельное присвоение
Вопрос:
Два приведенных ниже фрагмента кода должны печатать одно и то же, но они этого не делают.
ary = %W(1 2 5 6 B 8 5 4 6 5 6 9 7 A)
indx1 = 0...ary.index("B")
indx2 = (ary.index("A") 1)..-1
ary[indx1], ary[indx2] = ary[indx2], ary[indx1]
puts ary.inspect
ary = %W(1 2 5 6 B 8 5 4 6 5 6 9 7 A)
ary[0...ary.index("B")], ary[(ary.index("A") 1)..-1] = ary[(ary.index("A") 1)..-1], ary[0...ary.index("B")]
puts ary.inspect
Первый выводит:
["B", "8", "5", "4", "6", "5", "6", "9", "7", "A", nil, nil, nil, nil, "1", "2", "5", "6"]
и второй:
["B", "8", "5", "4", "6", "5", "6", "9", "7", "A", "1", "2", "5", "6"]
Разве они не должны печатать одно и то же? Мне они кажутся эквивалентными.
(С использованием Mac OSX 10.6.7 и ruby 1.9.2-p180)
Ответ №1:
Они отличаются тем, что в первом случае вы предварительно вычисляете индексы, а во втором вы вычисляете их динамически, и массив изменяется между первым присвоением и вторым.
Технически обе оценки RHS выполняются до выполнения назначений LHS, но оба назначения LHS не могут быть выполнены одновременно, поэтому в данном случае вы фактически видите, что
A, B = C, D
эквивалентно
A = C
B = D
Итак, первое, что вы делаете, это…
ary[0...ary.index("B")] = ary[(ary.index("A") 1)..-1]
в обоих случаях. Итак, ary теперь
["B", "8", "5", "4", "6", "5", "6", "9", "7", "A"]
Теперь изначально вы рассчитали indx1 и indx2 как 0...4
и 14..-1
соответственно, но теперь, если вы пересчитали значения indx1 и indx2, вы получите:
indx1 = 0...ary.index("B") #=> 0...0
indx2 = (ary.index("A") 1)..-1 #= 10..-1
Другими словами,
ary[indx2] = ary[indx1]
больше не эквивалентно
ary[(ary.index("A") 1)..-1] = ary[0...ary.index("B")]
Это,
ary = ["B", "8", "5", "4", "6", "5", "6", "9", "7", "A"]
ary[(ary.index("A") 1)..-1] = ary[0...ary.index("B")]
дает вам
ary #=> ["B", "8", "5", "4", "6", "5", "6", "9", "7", "A"]
в то время как
ary = ["B", "8", "5", "4", "6", "5", "6", "9", "7", "A"]
ary[indx2] = ary[indx1]
дает вам
ary #=> ["B", "8", "5", "4", "6", "5", "6", "9", "7", "A", nil, nil, nil, nil, "1", "2", "5", "6"]