Параллельное присваивание в ruby ​​работает по-разному для двух эквивалентных фрагментов кода - PullRequest
2 голосов
/ 07 мая 2011

Два фрагмента кода ниже должны печатать одно и то же, но это не так.

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 Ответ

4 голосов
/ 07 мая 2011

Они различаются, потому что в первом случае вы предварительно вычисляете индексы, а во втором вы рассчитываете их динамически, и массив изменяется между первым назначением и вторым.

Технически обе оценки RHS выполняются до выполнения назначений LHS, но оба назначения LHS не могут быть выполнены одновременно, поэтому в этом случае вы фактически видите, что

A, B = C, D

эквивалентно

A = C
B = D

Итак, первое, что вы делаете, это ...

ary[0...ary.index("B")] = ary[(ary.index("A") + 1)..-1]

в обоих случаях. Итак, теперь

["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"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...