Отсебятина Статьи Проекты
Облако тегов
Web CMS CSS htaccess HTML Javascript MySQL Php Безопасность Мониторы Новостная лента Оптимизация Ошибки Разработка сайта Часы Юзабилити оптимизация ошибки

Специфика работы логического оператора AND

Отсебятина от 22 августа 2009 года.    Теги: Php ошибки


Работая с чужим кодом, я периодически замечаю вещи, которые показывают, что пишущий их программист не до конца понимает работу оператора AND.

Периодически натыкаюсь на подобный код (абстрактный пример):

if ($a == 2)
if (myfunc($a) == 5)
  if ($a % 5 == 0)
   secondfunc($a);

Программисту нужно, чтобы переменная $a удовлетворяла всем условиям, но в качестве экономии ресурсов или нежелания подставлять неверные значение в последующие проверки, он разносит одну конструкцию на 3.

Нет, здесь не идет речь о следующих случаях:
if ($a == 2) {

if ($b == 3)
  echo 'Верно!';
else
  $b = 3;

}

В этом случае конструкцию можно заменить на
if ($a == 2 and $b == 3)
echo 'Верно!';
else if ($a == 2 and $b != 3)
$b = 3;

Но ведь первый случай рациональней, особенно, если вместо простого сравнения, данные проходят сложную обработку в функции. Во втором варианте получается, что $a проходит проверку два раза (если в первом if -> false), поэтому первый вариант этого случая оптимальнее.


Вернемся к первому примеру статьи. На первый взгляд, объединив все три условия в одно, мы будем проверять трижды нашу переменную, даже если она неверна изначально. Так и подумал тот программист, да разнес условие на 3 if.


Однако, все не так:
Оператор AND возвращает true, если правая и левая составляющие равны true. То есть, если первое составляющее условие вернуло false, интерпретатор, встретив оператор AND понимает, что условие уже не выполнится, независимо от дальнейших сравнений.
Поэтому, встретив хоть одно FALSE, интерпретатор выходит из условного блока, прекращая проверки и сравнения.

Если кто не верит, посмотрите примеры:
function myfunction () {

echo 'Вызов<br>';

return true;

}

if (myfunction() and myfunction())
echo "true";

Вернет:
Вызов
Вызов
true



Теперь немного поменяем код:
function myfunction () {

echo 'Вызов<br>';

return false;

}

if (myfunction() and myfunction())
echo "true";

Вернет:
Вызов

Как видно, первая функция вернула FALSE, интерпретатор, встретив AND, сразу выходит из блока и следующей проверки не происходит.


Давайте усложним код:

$GLOBALS["count"] = 2;
function myfunction () {

echo 'Вызов<br>';

$GLOBALS["count"]--;

return ($GLOBALS["count"]) ? true : false;

}
//   true     false
if (myfunction() and myfunction() and myfunction())
echo "true";

Как и ожидалось, функция вызовется 2 раза:
Вызов
Вызов
Во время второго вызова функция вернет false и интерпретатор выйдет из блока.

Еще вариант:


$GLOBALS["count"] = 2;
function myfunction () {

echo 'Вызов<br>';

$GLOBALS["count"]--;

return ($GLOBALS["count"]) ? true : false;

}
//   true     false
if (myfunction() and myfunction() or myfunction())
echo "true";

Вторая функция так же возвращает false, но после её вызова стоит оператор or, поэтому функция вызывается и третий раз:
Вызов
Вызов
Вызов
true
Вся конструкция равна true, потому что последняя функция вернет true (величина -1 == true)

PHP в данном случае эту конструкцию сгруппировал согласно левому приоритету AND и OR:
if ((myfunction() and myfunction()) or myfunction())



В принципе, схожая логика и у OR:
if (myfunction() or myfunction() and myfunction())
echo "true";
Вернет:
Вызов
true
Так как первая функция вернула true, а OR требует хотя бы одно true, то при выполнении условия, блок становится равен true, без вызова остальных функций.
Kreker  06.09.2009 в 01:07
Первое сообщение
Оставить сообщение






Любое копирование должно сопровождаться ссылкой на сайт.
Если вам что-то не понравилось — сообщайте.
Кича Владимир
x
Мне не нравится этот сайт, удалить его