Autor Zpráva
1Pupik1989
Profil
Je to spíše pro zajímavost.

Nicméně neví někdo proč následující kód vypíše nesmysl?
var x = 80;
var y = 50;
  
x ^= y ^= x ^= y;
  
console.log(x,y); // 0, 50

Je to zkráceno z:
x ^= y;
y ^= x;
x ^= y;

Přičemž třeba v PHP vypíšou oba příklady správně to samé.

Neví někdo v čem je háček? Nemá javascript limit přiřazování na jeden příkaz?
Chamurappi
Profil
Reaguji na 1Pupika1989:
Háček je v interpretaci operátorů, přesněji v pořadí, v jakém se vyhodnocují operandy.
Složené přiřazení je v JS (a tuším i v C# a v Javě) brané jen jako zkratka, x ^= y dopadne vždy přesně stejně jako x = x ^ y. Oproti tomu v PHP je nejspíš (stejně jako v C++) speciálním operátorem a je vyhodnocován víc doslovně (víc jako přiřazení). U operátorů v JS je vyhodnocený nejprve levý operand a pak pravý. I kdyby pravý operand provedl nějaké změny proměnné, která se využívá v levém operandu, tak se tato změna na získané hodnotě neprojeví. Naproti tomu v C++ se provádí složené přiřazení úpravu přímo na místě v paměti (nebo referenci objektu před rovnítkem), takže se v podstatě hodnota pravého operandu vyhodnotí dříve.

Tvůj příklad se tedy v JavaScriptu vyhodnocuje takto:
x ^= y ^= x ^= y;
x = x ^ (y = y ^ (x = x ^ y));
x = 80 ^ (y = y ^ (x = x ^ y));
x = 80 ^ (y = 50 ^ (x = x ^ y));
x = 80 ^ (y = 50 ^ (x = 80 ^ y));
x = 80 ^ (y = 50 ^ (x = 80 ^ 50));   // x = 80, y = 50
x = 80 ^ (y = 50 ^ 98);              // x = 98, y = 50
x = 80 ^ 80;                         // x = 98, y = 80
0;                                   // x =  0, y = 80

Kdežto v C++ (a tedy asi i v PHP) se vyhodnocuje takto:
x ^= y ^= x ^= y;
x ^= (y ^= (x ^= y));
x ^= (y ^= (x ^= 50));               // x = 80, y = 50
x ^= (y ^= 98);                      // x = 98, y = 50
x ^= 80;                             // x = 98, y = 80
50;                                  // x = 50, y = 80

Edit v reakci na _es níže: opraveno, díky za upozornění.
_es
Profil
Chamurappi [#2]:
V 3. riadku prvého kódu je asi chybička (nie 50 ale 80).

x ^= y dopadne vždy přesně stejně jako x = x ^ y.
Neplatí to v oboch prípadoch? Príkazy x = x ^ (y = y ^ (x = x ^ y));, x ^= (y ^= (x ^= y)); a x ^= y ^= x ^= y; sú ekvivalentné, len dajú v rôznych programovacích jazykoch odlišný výsledok.
1Pupik1989
Profil
Podle tedy v C++ a PHP se to vyhodnocuje podle mého předpokladu. Nejdřív výpočet a pak přiřazení a počítat od nejhlubšího potomka ve stromu. Čili v tom příkladu zprava doleva.

Co syntaktická analýza, to unikát koukám.
_es
Profil
1Pupik1989:
Co syntaktická analýza, to unikát koukám.
Syntaktická analýza je v oboch prípadoch rovnaká, len je rozdiel v tom, čo vysvetlil Chamurappi v [#2] o uchovávaní hodnôt operandov.
Je to podobné, ako keď kód v JS
var x = 1;
alert(x + (x += 1));
vypíše 3, no rovnaká situácia v PHP
$x = 1;
echo ($x + ($x += 1));
vypíše 4.
No
$x = 1;
echo (($x + 0) + ($x += 1));
už vypíše 3.
1Pupik1989
Profil
Píšu ze srandy překladač a po přeložení mi správně prohodil hodnoty. Kdežto JS ne. Tak jsem se nad tím pozastavil.

Děkuji za vysvětlení, alespoň vím na co si dát pozor.
Davex
Profil
Kontrolní otázka:

Jak dopadne vyhodnocení těchto výrazů?

a =  a + b - (b = a);
a =  a - (b = a) + b;
a =  b - (b = a) + a;
1Pupik1989
Profil
Davex: Skončí to "ReferenceError".

Nicméně základem je, že se závorka vykoná nejdříve, na to asi javascript letmo zanevřel.

Samý příklad jak jsem psal. Nejdřív je potřeba udělat první přiřazení v řadě, čili poslední a jet doleva. Je docela na prd, že každý překladač na to přistupuje jinak.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0