Termín Yoda conditions už jsem slyšel, dokonce pro tuhle věc, ale nebylo to míněno negativně. Běžně se to používá. Porovnejte například pro Javu:
myVar.equals(„blue“)
„blue“.equals(myVar)
Výrazy nejsou ekvivalentní – pokud je vaše proměnná myVar null, první verze hodí výjimku. A jsou tu i překladače, které to dokáží využít pro optimalizaci (volání metody konstanty známé při překladu). Každopádně je pravda, že ten zápis trochu trhá oči, člověk za tím „blue“ vidí spíš řetězec než objekt.
Tzv. yoda conditions IMHO pochadzaju z C/C++ pretoze ak si spravne pamatam vyraz
if (0 == myVar) a if (myVar == 0)
su sice ekvivalente, ale ak programator zabudol jedno = tak
if (myVar = 0) je platny lvalue(?) vyraz ktory sa vzdy vyhodnoti ako true teda if vzdy prejde, oproti tomu
if (0 = myVar) je syntakticka chyba ktoru prekladac zachyti a nepovoli kompilaciu. Preto sa ako best practice odporucalo pouzivat tento zapis.
…teda nechci si hrat na prilis chytreho, ale pokud si spravne vzpominam (myValue = 0)
je vyraz, jehoz hodnotou je 0, takze if (myValue = 0)
NEPROJDE.
Nebezpeci toho zapomenuteho rovnitka tkvi v tom, ze jsem tim prave zmenil hodnotu myValue, coz jsem pravdepodobne nechtel…
V tom smeru pry byl kdyzi i nejaky pokus o commit bezpecnostni diry do jadra Linuxu – if ( ... ... ... (uid = 0) )
Já jsem se s tímhle hodně jednou zapotil v PHP. Podle mě interpretr najprve přiřadí proměnné 0 a výsledek vyhodnotí jako úspěšnou operaci (tedy true). Dobrou hodinu jsem si lámal hlavu nad tím, že se mi jako true vyhodnocuje výraz, kde daná proměnná rozhodně 0 neni.
Naštěstí Python už má tohle rozumně ošetřené a výraz „if var = 0“ vyhodí jako syntaktickou chybu.
Neprojde. Rika to zaprve logika, zadruhe jsem si to prave nechal zkompilovat (jesteze existuji online kompilatory C :) )
Prirazeni je v C vyrazem a vraci onu prirazenou hodnotu. Priradim 0, vysledkem je 0 → false → if neprojde.
Chyba je jen v te modifikaci „porovnavane“ promenne, ktera v tomto pripade nebyla zamyslena.
Srandičky, a ona to je někdy vážná věc… :o
Místo
if (var & FLAG)
jsem omylem napsal
if (var && FLAG)
a byl průser (protože za tím náhodou následovalo smazání veškerých dat :-/).
Co se týká toho přiřazení na místě porovnání, gcc
se zapnutým -Wall
(rozumné, pokud nejsem přímo -pedantic
) mi samozřejmě upozorní:
warning: suggest parentheses around assignment used as truth value
A pokud skutečně chci najednou přiřazovat a výsledek použít pro porovnání A nenaštvat gcc
, tak napíšu:
if ((var = func()) == value)
Je to jen věc coding standards a jejich dodržování. A já jsem rád, že jsem zatím nikde nemusel používat třeba zrovna Yoda conditions.