Пишу, по большей части, про историю, свою жизнь и немного про программирование.

И и И (логические выражения в PHP)

В ПХП есть два набора команд булевой логики — многим более привычные «&&» и «||», но кроме них — напоминающие о Бейсике и Эскюэле «and» и «or». Даже программирующие на языке годами часто не знают чем они отличаются, между тем употребление второго набора может привести к трудноуловимым багам, потому что ведут они себя чуть иначе.

Вся разница заключается в приоритетах выполнения, большинство языков, разбирая выражение, опирается на приоритеты выполнения, например, умножение приоритетней сложения, этому нас учат в школе, в ПХП и многих других языках — так же: 2 + 2 × 2 = 6, а не 8.

Так вот. Набор «and» и «or» — чуть ли не самые низкоприоритетные из всего, что может встретиться, а «&&» и «||» находятся где-то посередине. Поясню примером. Команда присваивания выше «по табелю о рангах», чем «or», но ниже, чем «||»:

// какая-то переменная, значение которой в коде,
// к этому моменту, стало true
$check = true;

// а это другая контрольная переменная, где-то в коде
// она приобрела значение false
$criteria = false;

// и вот мы подходим к главному
$ret_bool = $criteria ||  $check;
$ret_logic = $criteria or $check;

var_dump($ret_bool, $ret_logic);

Будут ли отличаться значения переменных ret_bool и ret_logic после выполнения программы? Конечно будут, иначе я бы не писал этут статью, неправда ли? Значение первой будет true, второй — false.

Почему так? Приоритеты! ПХП, исполняя предпоследние две строчки кода видит их как-то так:

$ret_bool = ($criteria || $check);
($ret_logic = $criteria) or $check;

Исполнение идёт строго по приоритетам, так как во втором случае операция присваивания имеет больший приоритет, чем «or», первым выполняется именно она, а проверка переменной check осуществляется, но её результат отбрасывается.

Это отлично подходит для программировая в «хакерском» стиле:

$ret_logic = $criteria or CheckSomething();

Функция CheckSomething() вызовется только в том случае, если criteria будет равна false или эквиваленту, но зато результат функции никак не повлияет на значение ret_logic.

Впрочем, я такой способ программирования крайне не рекомендую — для современных программистов он сложен.

28 комментариев
Горбунов Олег 2014

Я кстати, пользуюсь «набором из бейсика», поскольку по диагонали оно читается в коде на порядки легче. Приоритеты скобками задаю всегда — ИДЕ подсвечивают, позволяя разбирать довольно сложные условия.
Не знаю, хорошо это или плохо, просто так привык. :)

Евгений Степанищев (bolknote.ru) 2014

Комментарий для Горбунов Олег:

Я кстати, пользуюсь «набором из бейсика», поскольку по диагонали оно читается в коде на порядки легче.

Это вопрос привычки. Одни значки и другие значки.

Приоритеты скобками задаю всегда — ИДЕ подсвечивают, позволяя разбирать довольно сложные условия.
Не знаю, хорошо это или плохо, просто так привык. :)

Плохо. Не нужно лишнего, это как ударения в каждом слове расставлять — больше знаком без какого-либо смысла. А в случае конструкций это просто не работает: http://bolknote.ru/all/4143

Бабаев Александр (bealex.moikrug.ru) 2014

для современных программистов он сложен.

Отлично, отлично :)

hshhhhh (hshhhhh.name) 2014

для современных программистов он сложен.

смешно конечно, но вообще зачем так усложнять код? по мне так проще написать в три строчки. через три года будет проще разбираться почему не работает :).

PastorGL 2014

для современных программистов он сложен.

Я ещё со времён Бейсика (то есть, чуть меньше последних 25 лет) всегда расставляю скобки в логических выражениях и вокруг тернарного оператора. Вне зависимости от того, на каком языке пишу. Это правило как раз снимает необходимость помнить, в каком языке какие приоритеты.

А вещи типа

$ret_logic = $criteria or CheckSomething();

вообще стараюсь не использовать. Мало ли, вдруг сам не пойму, что я тут имел в виду, через пару лет копаясь в старом коде.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для hshhhhh.name:

смешно конечно, но вообще зачем так усложнять код? по мне так проще написать в три строчки. через три года будет проще разбираться почему не работает :)

Самое смешное, что никакого переусложнения нет. Это очень простое выражение. Но современные программисты считают его сложным.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для PastorGL:

Это правило как раз снимает необходимость помнить, в каком языке какие приоритеты.

Это вопрос владения языком. Современный подход подразумевает, что лучше иметь низкий уровень в куче языков, чем идеально знать 1—2.

hshhhhh (hshhhhh.name) 2014

Комментарий для Евгения Степанищева:

Самое смешное, что никакого переусложнения нет. Это очень простое выражение. Но современные программисты считают его сложным.

Я не считаю его сложным, но просто из-за того что я and/or не пользовался уже много лет я не сразу найду ошибку / пойму как оно работает.

То есть я всегда знал что там разные приоритеты и да, глаз у меня за это зацепиться, но мне будет нужно лезть в доку.

Это вопрос владения языком. Современный подход подразумевает, что лучше иметь низкий уровень в куче языков, чем идеально знать 1—2.

Тут дело не в современном подходе, а в современных реалиах. Вот знаешь ты сейчас, например, идеально пхп, а интересную работу найти совсем не так просто как 5 лет назад.

А на C что 10 лет назад, что 20 -​-​ можно было найти работу.

Вопрос в мимолётности языков.

Ну и самая большая проблема в том что сейчас люди не учат языки программирования -​-​ люди изучают фреймворки к языкам программирования.
Типа в требованиях редко можно найти Ruby/Python, но почти всегда Ruby On Rails / Django.

В современом мире работодателю редко нужны люди которые зачем-то помнят приоритеты для and / or если ими не пользуются %)

Евгений Степанищев (bolknote.ru) 2014

Комментарий для hshhhhh.name:

В современом мире работодателю редко нужны люди которые зачем-то помнят приоритеты для and / or если ими не пользуются %)

Работодатель тут не причём. Это вопрос профессионализма. Именно поэтому я могу найти любую ошибку в чужом коде (при этом я не программистом работаю), а из кучи программистов вокруг — считанные единицы.

hshhhhh (hshhhhh.name) 2014

Комментарий для Евгения Степанищева:

Работодатель тут не причём. Это вопрос профессионализма. Именно поэтому я могу найти любую ошибку в чужом коде (при этом я не программистом работаю), а из кучи программистов вокруг — считанные единицы.

Найти ошибку это одно.
Я про то что в пхп достаточно большое колличество вещей не совсем очевидно и в них надо вникать и разбираться. Эти вот приоритеты или нюансы с кастованием.

Я считаю что знать про них надо, но при этом я не совсем понимаю зачем писать код в котором могут быть ошибки.

То есть привёденный пример в статье: $ret_logic = $criteria or CheckSomething();
На мой взгляд совсем не пример хакерского кода, а кода плохого.
в чем проблема записать это в две строки?
$ret_logic = $criteria;
$criteria || CheckSometing();

Я бы ещё и в иф обернул просто потому что в пхп так писать не принято. На мой взгляд это такое же хакерский код как и писать if () без фигурных скобок. Можно -​-​ да. Зачем? Непонятно.

hshhhhh (hshhhhh.name) 2014

Комментарий для Евгения Степанищева:

Если писать этот «хакерский код» как прототип с целью склепать на коленке что-то быстрое и важна скорость -​-​ да, конечно.

В реальной жизни в любом коде должны быть такое дикое колличество проверок, то экономия одной строчки (и усложнение логики) не влияет ни на что. Я не понимаю зачем :).

hshhhhh (hshhhhh.name) 2014

Комментарий для Евгения Степанищева:

Опять же если рассматривать их как радость от познания возможностей компилятора -​-​ да сам бог велел.

Но вот, например, в пхп есть анонимные функции. Анонимные функции это очень круто. Только в пхп ими практически не пользуются, но ведь они есть. Почему ими не пользуются?

zg (zg.livejournal.com) 2014

ну да, раньше и трава была зеленее и программисты лучше.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для hshhhhh.name:

Если писать этот «хакерский код» как прототип с целью склепать на коленке что-то быстрое и важна скорость — да, конечно.

Нет, это не он. Просто внутри некоторых языков программирования тоже появляется «мейнстрим». В ПХП это можно назвать «пишем на детсадовском в Си» (без указателей и прочих прелестей Си).

Но вот, например, в пхп есть анонимные функции. Анонимные функции это очень круто. Только в пхп ими практически не пользуются, но ведь они есть. Почему ими не пользуются?

Пользуются. Только не те, кто клепает маленькие сайты — во-первых, там всё равно как писать, во-вторых, хостеры лениво обновляются. Те, кто делает код, который требует выделенный хостинг, используют все прелести новых версий — это просто очень удобно.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для zg.livejournal.com:

ну да, раньше и трава была зеленее и программисты лучше.

Я уже более 15 лет нанимаю программистов. Вижу куда движется всё.

zg (zg.livejournal.com) 2014

Комментарий для Евгения Степанищева:

Я уже более 15 лет нанимаю программистов.

это очень маленький срез.

Вижу куда движется всё.

не очень понятно, как по такому маленькому срезу можно прямо таки видеть всё.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для zg.livejournal.com:

это очень маленький срез.

Это нормальный срез.

Efendy 2014

Во многих языках приоритет у && и and разный, но такой нюанс как у тебя в примере — это изобретение пхп и оно не логично

zg (zg.livejournal.com) 2014

Это нормальный срез.

почему вы так решили?

Евгений Степанищев (bolknote.ru) 2014

Комментарий для Efendy:

Во многих языках приоритет у && и and разный, но такой нюанс как у тебя в примере — это изобретение пхп и оно не логично

Если разный (а где, кстати, такое ещё есть?), то это не изобретение ПХП, а работает так же везде или схожим образом, так как пример и строится на разнице приоритетов.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для zg.livejournal.com:

почему вы так решили?

А почему вы так решили? Я ответил одним голословным утверждением на другое.

DuMOHsmol (anothersite.ru) 2014

А еще есть редко упоминаемый оператор «<>», синоним «!=». Насколько помню, приоритеты у них одинаковые.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для anothersite.ru:

Да, они полные эквиваленты. Я когда-то в ПХП пользовался только <>.

Илья 2014

Комментарий для Евгения Степанищева:

Если разный (а где, кстати, такое ещё есть?)

Такая же ботва в Руби: http://www.techotopia.com/index.php/Ruby_Operator_Precedence
Частенько использую их в стиле

redirect_to ’xxx’ and return
check_something or raise some_exception

Евгений Степанищев (bolknote.ru) 2014

Комментарий для Илья:

Надо же! Ещё и приоритеты примерно как в ПХП.

Илья 2014

Комментарий для Евгения Степанищева:

Да, и такая же проблема с присваиванием и вообще. Поэтому очень быстро отучаешься использовать в сложных случаях, так как почти всегда оно работает не так, как ожидаешь. Фактически, только как в примере выше и использую, удобно — емко, кратко, вместе с тем читабельно.

Efendy 2014

Комментарий для Евгения Степанищева:

В perl разный приоритет, вот первое что выдал гугл http://hscripts.com/tutorials/perl/operators/oprpreced.php

Евгений Степанищев (bolknote.ru) 2014

Комментарий для Efendy:

Странно, что Перл в голову мне не пришёл.