Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   XOR swap: ЧЯДНТ? (https://javascript.ru/forum/misc/32545-xor-swap-chyadnt.html)

Дзен-трансгуманист 20.10.2012 10:15

XOR swap: ЧЯДНТ?
 
Нет, я не задрот оптимизации. :)
Просто мне стало интересно.
var x = 10, y = 20;

x ^= y;
y ^= x;
x ^= y;

alert("x = " + x + ", y = " + y); // Всё ништяк

x = 10; y = 20;

x ^= (y ^= (x ^= y));

alert("x = " + x + ", y = " + y); // WTF???


Аналогичная операция через обычную арифметику:
var x = 10, y = 20;

x += y;
y = x - y;
x -= y;

alert("x = " + x + ", y = " + y); // Всё ништяк

x = 10; y = 20;

x -= (y = (x += y) - y);

alert("x = " + x + ", y = " + y); // И тут та же фигня


Выходит, что и тут и там в самом левом "икс" исходное значение сохраняется вплоть до последней операции, тогда как должно было измениться немедленно при (x ^= y) и (x += y) соответственно.

Это нормально с точки зрения языка?
Если да, то почему, где тут логика, ткните пальцем.

melky 20.10.2012 11:56

Цитата:

Сообщение от Дзен-трансгуманист
Выходит, что и тут и там в самом левом "икс" исходное значение сохраняется вплоть до последней операции, тогда как должно было измениться немедленно при (x ^= y) и (x += y) соответственно.

неа

var x = 10, y = 20;

x -= (y = ((x += y), alert("x = " + x), x) - y);


ещё примерчик, без игреков, чтобы было легче усвоить:

x = 3;

x += 3; // x = 6
x -= 9 - x; // 9 - 6 === 3

alert(x);

x = 3;

x -= ( 9 - ( x += 3 ) );

alert(x); // 0


после этого углубляемся в спеку :
  1. Пусть lref будет результатом вычисления LeftHandSideExpression.
  2. Пусть lval будет GetValue(lref).
  3. Пусть rref будет результатом вычисления AssignmentExpression.
  4. Пусть rval будет GetValue(rref).
  5. Пусть r будет результатом применения оператора @ к lval и rval.
  6. Вызвать PutValue(lref, r) и вернуть r.

во втором примере (моём) берётся значение икса (3), далее вычисляется значение правой стороны ( тоже 3), потом честно применяется к ним минус, получаем нуль.

фишка в том, что X изменяется, но двиг уже взял его значение (старое), и не обновляет его (ящитаю)

т.е. в числах всё происходит так :
3 -  (9 -  (3 + 3)); // 3 - (6 - 3) -> 3 - 3.

nerv_ 20.10.2012 12:30

melky, не перестаешь меня удивлять
Цитата:

Сообщение от melky
ящитаю

:D

Дзен-трансгуманист, думаю, абсолютно нормально. Попробую аргументировать:
x -= (y = (x += y) - y);

присвоение с операцией выполняется следующим образом:
1. сперва вычисляется выражения справа от [B]x -= ...[/B], а затем происходит присвоение
2. т.е. здесь [B]x += y[/B] его быть не может потому, что оно должно произойти позже (после вычисления всего выражения)
3. иными словами [B]x += y[/B] в данном случае работает как [B]x + y[/B]

Это как бы мое мнение не опираясь на спецификацию :)

Ну а коли речь зашла о нормальности, то подобные конструкции сами по себе ай-яй-яй )

melky 20.10.2012 12:32

Цитата:

Сообщение от nerv_
melky, не перестаешь меня удивлять

мы любим луркмоар :)
Цитата:

Сообщение от nerv_
Это как бы мое мнение не опираясь на спецификацию

как тебе мой ответ с опором на спецификацию?

Цитата:

Сообщение от nerv_
т.е. здесь x += y его быть не может потому, что оно должно произойти позже (после вычисления всего выражения)

м-м, можно припихнуть туда алерт, и будет видно, что значение икса поменялось (см. мой пост)

nerv_ 20.10.2012 13:06

Цитата:

Сообщение от melky
как тебе мой ответ с опором на спецификацию?

вроде как лучше, чем мой :)
Цитата:

Сообщение от melky
м-м, можно припихнуть туда алерт, и будет видно, что значение икса поменялось (см. мой пост)

угу

x-yuri 20.10.2012 17:54

Цитата:

Сообщение от Дзен-трансгуманист
Это нормально с точки зрения языка?

http://lurkmore.to/I%2B%2B

B@rmaley.e><e 20.10.2012 22:07

Хоть всё уже и расписали, вставлю свои 5 копеек:
Запись вида x ^= y (как и подобные) эквивалентна записи вида x = x ^ y. Понятно, что если во втором операнде, т.е. в выражении y изменяется x, то на первый операнд оно уже не влияет, т.к. тот уже был вычислен.

Дзен-трансгуманист 21.10.2012 08:28

Ага, всё, теперь вкурил. Значит я просто неверно понимал механизм составного присваивания в JS.)
Спасибо всем. :)

x-yuri 24.10.2012 01:20

Цитата:

Сообщение от B@rmaley.e><e
Запись вида x ^= y (как и подобные) эквивалентна записи вида x = x ^ y. Понятно, что если во втором операнде, т.е. в выражении y изменяется x, то на первый операнд оно уже не влияет, т.к. тот уже был вычислен.

Не всем понятно, см. ссылку выше.


Часовой пояс GMT +3, время: 09:27.