Теперь пример поинтереснее. Буду объяснять подробно.
Допустим, имеем такой код (РНР):
<?
if($enabled)
{
if($has_property)
do_it();
}
else
do_it();
?>
Мне он не нравится по нескольким причинам: во-первых, do_it() может быть заменён не таким примитивным вызовом, а каким-то блоком команд, и тогда этот кусок придётся повторить, а при последующих правках надо будет не забыть поправить в обоих местах; во-вторых, таких веток можно навесить сколько угодно, и если в данном случае ещё можно сомневаться в необходимости оптимизации, то в случае обрастания этой структуры улучшение через упрощение станет необходимым шагом.
Что можно сделать? Допустим, переменная $enabled есть предикат А, а переменная $has_property есть предикат В (Что такое предикат? Это утверждение, которое либо ложно, либо истинно, например, "жена беременна"). Теперь нарисуем карту Карно, помним такую?
A
¦-----¦-----¦
¦ ¦ ¦
¦-----¦-----¦
¦ ¦ ¦B
¦-----¦-----¦
Здесь 4 ячейки - максимальное количество состояний, которое может быть в нашем случае, т.к. каждый предикат может быть в одном из 2 состояний (4 = количество состояний в степени количества переменных = 2 в квадрате). Теперь перебираем состояния нашего условия, и если оно истинно (т.е. если запустится функция "do_it()" ), ставим в соответствующую ячейку единичку, иначе нолик.
Итак, ячейка 1 (первый столбец, первая строка). В ней А истинно (А стоит прямо над ней), а В - нет (В стоит во второй строке). Что же даёт наша задача, если А=$enabled=да и И=$has_property=нет? Ничего: программа успешно пройдет первую строку [if($enabled)], и пропустит вторую [if($has_property)]. Значит, ставим в первую ячейку нашей таблицы 0.
Ячейка 2 (второй столбец первой строки). Здесь А=нет и В=нет. Как видно по программе, если А=нет, то запускается else, и do_it() выполнится, значит, ставим единичку.
Ячейка 3 (первый столбец, вторая строка). А=да, В=да. В итоге будет единица, так как программа пройдёт оба if и запустит do_it().
Ячейка 4 (второй стоблец, вторая строка). Здесь опять А=нет, а В=да.Как снова видно по программе, если А=нет, то запускается else, значит,ещё одна единичка.
В итоге получаем такую картину:
A
¦-----¦-----¦
¦ 0 ¦ 1 ¦
¦-----¦-----¦
¦ 1 ¦ 1 ¦B
¦-----¦-----¦
Вот теперь начинается оптимизация. Это называется склеивание: мы в уме группируем в команду по две сначала обе нижние единицы, потом две правые. Таким образом, получаем две группы единиц, между которыми нужно поставить знак плюс (дизъюнкция, она же OR, она же ¦¦ ) - таковы правила (не было бы единицы в позиции {2,2} - нечего бы было группировать). То есть первая группа единиц - это две единички во второй строке: они обе сработают, когда В=да (потому что стоят в строке, где В=да). Вторая группа единиц стоит во втором столбце, там А=нет. Получается, что первая группа = В, вторая = !А (А=нет, "не А"или "А есть ложь").
Таким образом, наше выражение записывается так: (!А OR В).
Делая обратную расшифровку, получаем:
<?
if(!$enabled ¦¦ $has_property)
do_it();
?>
Нравится? Мне очень. Да, сперва не слишком очевидное выражение для последующих правщиков, но зато это можно восполнить комментированием рядом с условием.
Желаю удачи в разборе полётов 3 переменных!