Сегодня поближе познакомимся с short circuit evaluation: выясним что это за зверь такой, посмотрим примеры и выясним, как он нам может помочь.
Для начала немного теории. Short circuit evaluation (не могу предложить простого русского перевода) - это стратегия в языках программирования, которая используется, чтобы избежать ненужных вычислений.
Лучше всего это понять на примере булевых выражений. Допустим, мы проверяем условие вида if (checkSomething() && checkSomethingElse())
. Если checkSomething()
вернет false
, то true
в итоге уже никак не получить, следовательно, вычислять второе значение в checkSomethingElse()
не имеет смысла - любое вычисленное значение никак не повлияет на итоговый результат.
Теперь примеры - short circuit evaluation в действии. Определим четыре функции, две из них возвращают true
, две других - false
. Для проверки поместим в тела этих функций вывод сообщений:
function returnTrue(): bool
{
echo 'Вызван метод ' . __METHOD__ . PHP_EOL;
return true;
}
function returnTrueToo(): bool
{
echo 'Вызван метод ' . __METHOD__ . PHP_EOL;
return true;
}
function returnFalse(): bool
{
echo 'Вызван метод ' . __METHOD__ . PHP_EOL;
return false;
}
function returnFalseToo(): bool
{
echo 'Вызван метод ' . __METHOD__ . PHP_EOL;
return false;
}
Проверяем:
if (returnFalse() && returnTrue()) {
echo 'Эта строка не выведется';
} else {
echo 'Эта строка выведется и это правильно';
}
// Вывод
Вызван метод returnFalse
Эта строка выведется и это правильно
Как видим - short circuit evaluation действительно работает: так как &&
вернет true
только в случае если оба аргумента равны true
, а первый вычисленный аргумент не равен true
, то вычислять второй не имеет смысла, итоговое выражение от этого не станет true
. Поэтому видим, что выполнилась только первая функция returnFalse
.
Пример посложнее:
if ((returnTrue() || returnFalse()) && (returnFalseToo() && returnTrueToo())) {
echo 'Эта строка не выведется';
} else {
echo 'Эта строка выведется и это правильно';
}
// Вывод
Вызван метод returnTrue
Вызван метод returnFalseToo
Эта строка выведется и это правильно
Третья проверка показывает, что если все условия могут повлиять на результат - то все они и проверятся:
if (returnFalse() || returnFalseToo() || returnTrueToo()) {
echo 'Эта строка выведется и это правильно';
} else {
echo 'Эта строка не выведется';
}
// Вывод
Вызван метод returnFalse
Вызван метод returnFalseToo
Вызван метод returnTrueToo
Эта строка выведется и это правильно
Итак, short circuit evaluation действительно работает и не вызывает функции, если их выполнение не повлияет на результат вычисления. И стоит это учитывать в ваших условиях. Например, рассмотрим такой гипотетический случай:
if (returnsTrue() || checkSomethingFromApi()) {
// more code
}
Здесь checkSomethingFromApi
некая функция, которая достает результат из апи, что-либо проверяет в нем и возвращает какой-то результат. Если вы будете думать, что checkSomethingFromApi
будет вызываться всегда, то увы. Так как первой части достаточно для всего результата, то функция checkSomethingFromApi
не вызовется никогда. И если checkSomethingFromApi
дополнительно делает какое-то еще, явно не обозначенное действие (например, пишет в БД или в кеш), то это действие не выполнится, и в БД не запишется ничего. Следовательно, вам гарантированы часы дебага и разочарование, что "ларчик просто открывался". Инспекции PHPStorm, кстати, могут обратить ваше внимание на такое поведение.
Теперь перейдем к другому моменту: что если мы объединим некоторые логические условия в скобки и возьмем от них отрицание. Будет ли применён short circuit evaluation или будут выполнены все вычисления в скобках, и только потом инвертируется результат? Смотрим в пример:
if (!(returnTrue() || returnFalse()) || !(returnFalse() && returnFalseToo())) {
echo 'Эта строка выведется и это правильно';
} else {
echo 'Эта строка не выведется';
}
// Вывод
Вызван метод returnTrue
Вызван метод returnFalse
Эта строка выведется и это правильно
Как видим, и тут срабатывает short circuit evaluation. В первом условии returnTrue()
однозначно определяет результат всего условия как true
, отрицание дает false
, значит надо перейти к вычислению второго условия. Во втором условии returnFalse()
также достаточно для определения результата, и отрицание false
дает true
. Как видим - вместо предполагаемых четырех функций выполнились всего лишь две.
Итак, мы разобрались что такое short circuit evaluation, посмотрели примеры с его использованием и даже выяснили один подводный камень его использования.
Комментариев нет:
Отправить комментарий