And i &&

W przejętej do utrzymania aplikacji napisanej w PHP zauważyłem, że podczas testowania warunków if() zamiast używania operatorów && i || stosowano and i or. Ponieważ ja zawsze używałem tych pierwszych postanowiłem sprawdzić czym to się różni. Po lekturze dokumentacji i sieci można powiedzieć, że sprawa kręci się wokół dwóch rzeczy: kolejność operatorów (operator precedence) i short-circuit evaluation. To drugie nie wiem jak ładnie przetłumaczyć, ale chodzi o jak najszybsze zakończenie sprawdzania warunków true/false – to znaczy kiedy silnik PHP uzna, że zna już odpowiedź, to nie sprawdza pozostałych warunków.

Ma to miejsce kiedy:

  • pierwsza część warunku and zwraca false – bo od razu wiadomo, że cały warunek zwróci false
  • pierwsza część warunku or zwraca wartość true – bo od razu wiadomo, że cały warunek zwróci true


Dla przypomnienia krótka powtórka z logiki matematycznej: and zwraca true tylko jeśli oba elementy są true, or zwraca false tylko jeśli oba elementy są false.

A     B    AND   OR
0     0     0     0
0     1     0     1
1     0     0     1
1     1     1     1

Dla zilustrowania zagadnienia posłużę się przykładem

<?php

$a = true || false;
$b = (true || false);
var_dump($a, $b);

$c = true or false;
$d = (true or false);
var_dump($c, $d);

$e = false || true;
$f = (false || true);
var_dump($e, $f);

$g = false or true;
$h = (false or true);
var_dump($g, $h);

echo "----------\n";

$A = true && false;
$B = (true && false);
var_dump($A, $B);

$C = true and false;
$D = (true and false);
var_dump($C, $D);

$E = false && true;
$F = (false && true);
var_dump($E, $F);

$G = false and true;
$H = (false and true);
var_dump($G, $H);

?>

Co zwróci:

bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(false)
bool(true)
----------
bool(false)
bool(false)
bool(true)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)

Dlaczego zwracane są takie wartości? Jeszcze krótkie przypomnienie z kolejności operatorów. Z używanych powyżej od najważniejszego:
&&
||
=
and
or

Short-circuit evaluation ma miejsce w przykładach $a, $b, $c, $d, $E, $F.
W przykładach $e, $f, $h, $A, $B, $D, $H PHP musi obliczyć wynik, bo go nie zna na podstawie pierwszego warunku. Pozostają do omówienia przypadki $g, $C i $G. Tu sprawa wygląda inaczej z powodu kolejności operatorów.

$g = false or true zwraca false, ponieważ najpierw do zmiennej $g jest przypisywana wartość false, a następnie następuje operacja or true, która niczego niczemu nie przypisuje. Taka instrukcja to jakby złożenie dwóch poleceń:
$g = false;
$g or true;
Drugie z nich po prostu robi operację porównania, która zwraca true, ale nie przypisuje już tego zmiennej $g.

Tak samo w pozostałych przypadkach:
$C = true and false zwraca true:
$C = true;
$C and false;

$G = false and true zwraca false:
$G = false;
$G and true;

Żeby jeszcze bardziej unaocznić działanie short-circuit evaluation taki przykład:
if(true || $n = 1) {
echo $n;
}
Zmienna $n nie pojawi się na ekranie, ponieważ silnik PHP uznał, że warunek if zwraca true i reszty instrukcji już nie wykonuje.

No, to na koniec jeszcze wnioski. Jeśli nie chcesz się zamotać w warunkach – stosuj nawiasy. Jeśli chcesz przyspieszyć działanie warunków – w przypadkach or dawaj warunki zwracające true jak najbliżej lewej strony (np. 1 or 0). W przypadku and najbliżej lewej strony dawaj warunki false (np. 0 and 1).

Advertisements

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s