И и И (логические выражения в 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.

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

Горбунов Олег (инкогнито)
27 мая 2014, 07:40

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

Евгений Степанищев (bolknote.ru)
27 мая 2014, 08:02, ответ предназначен Горбунову Олегу

Я кстати, пользуюсь «набором из бейсика», поскольку по диагонали оно читается в коде на порядки легче.
Это вопрос привычки. Одни значки и другие значки.
Приоритеты скобками задаю всегда — ИДЕ подсвечивают, позволяя разбирать довольно сложные условия.
Не знаю, хорошо это или плохо, просто так привык. :)
Плохо. Не нужно лишнего, это как ударения в каждом слове расставлять — больше знаком без какого-либо смысла. А в случае конструкций это просто не работает: http://bolknote.ru/2014/03/05/~4143

Бабаев Александр (bealex.moikrug.ru)
27 мая 2014, 09:07

для современных программистов он сложен.
Отлично, отлично :)

hshhhhh (hshhhhh.name)
27 мая 2014, 13:39

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

PastorGL (инкогнито)
27 мая 2014, 13:57

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

А вещи типа
$ret_logic = $criteria or CheckSomething();
вообще стараюсь не использовать. Мало ли, вдруг сам не пойму, что я тут имел в виду, через пару лет копаясь в старом коде.

Евгений Степанищев (bolknote.ru)
27 мая 2014, 14:00, ответ предназначен hshhhhh (hshhhhh.name):

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

Евгений Степанищев (bolknote.ru)
27 мая 2014, 14:01, ответ предназначен PastorGL

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

hshhhhh (hshhhhh.name)
27 мая 2014, 15:08, ответ предназначен Евгений Степанищев (bolknote.ru):

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

То есть я всегда знал что там разные приоритеты и да, глаз у меня за это зацепиться, но мне будет нужно лезть в доку.
Это вопрос владения языком. Современный подход подразумевает, что лучше иметь низкий уровень в куче языков, чем идеально знать 1—2.
Тут дело не в современном подходе, а в современных реалиах. Вот знаешь ты сейчас, например, идеально пхп, а интересную работу найти совсем не так просто как 5 лет назад.

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

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

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

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

Евгений Степанищев (bolknote.ru)
27 мая 2014, 15:50, ответ предназначен hshhhhh (hshhhhh.name):

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

hshhhhh (hshhhhh.name)
27 мая 2014, 16:12, ответ предназначен Евгений Степанищев (bolknote.ru):

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

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

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

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

hshhhhh (hshhhhh.name)
27 мая 2014, 16:14, ответ предназначен Евгений Степанищев (bolknote.ru):

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

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

hshhhhh (hshhhhh.name)
27 мая 2014, 16:20, ответ предназначен Евгений Степанищев (bolknote.ru):

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

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

zg (zg.livejournal.com)
27 мая 2014, 17:51

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

Евгений Степанищев (bolknote.ru)
27 мая 2014, 19:36, ответ предназначен hshhhhh (hshhhhh.name):

Если писать этот «хакерский код» как прототип с целью склепать на коленке что-то быстрое и важна скорость — да, конечно.
Нет, это не он. Просто внутри некоторых языков программирования тоже появляется «мейнстрим». В ПХП это можно назвать «пишем на детсадовском в Си» (без указателей и прочих прелестей Си).
Но вот, например, в пхп есть анонимные функции. Анонимные функции это очень круто. Только в пхп ими практически не пользуются, но ведь они есть. Почему ими не пользуются?
Пользуются. Только не те, кто клепает маленькие сайты — во-первых, там всё равно как писать, во-вторых, хостеры лениво обновляются. Те, кто делает код, который требует выделенный хостинг, используют все прелести новых версий — это просто очень удобно.

Евгений Степанищев (bolknote.ru)
27 мая 2014, 19:36, ответ предназначен zg (zg.livejournal.com):

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

zg (zg.livejournal.com)
27 мая 2014, 23:23, ответ предназначен Евгений Степанищев (bolknote.ru):

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

Евгений Степанищев (bolknote.ru)
28 мая 2014, 06:05, ответ предназначен zg (zg.livejournal.com):

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

Efendy (инкогнито)
28 мая 2014, 09:52

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

zg (zg.livejournal.com)
28 мая 2014, 10:49

Это нормальный срез.
почему вы так решили?

Евгений Степанищев (bolknote.ru)
28 мая 2014, 12:50, ответ предназначен Efendy

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

Евгений Степанищев (bolknote.ru)
28 мая 2014, 12:51, ответ предназначен zg (zg.livejournal.com):

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

DuMOHsmol (anothersite.ru)
28 мая 2014, 19:17

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

Евгений Степанищев (bolknote.ru)
29 мая 2014, 06:12, ответ предназначен DuMOHsmol (anothersite.ru):

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

Илья (инкогнито)
29 мая 2014, 08:08, ответ предназначен Евгений Степанищев (bolknote.ru):

Если разный (а где, кстати, такое ещё есть?)
Такая же ботва в Руби: http://www.techotopia.com/index.php/Ruby_Operator_Precedence
Частенько использую их в стиле

redirect_to 'xxx' and return
check_something or raise some_exception

Евгений Степанищев (bolknote.ru)
29 мая 2014, 09:52, ответ предназначен Илье

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

Илья (инкогнито)
29 мая 2014, 12:40, ответ предназначен Евгений Степанищев (bolknote.ru):

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

Efendy (инкогнито)
30 мая 2014, 23:11, ответ предназначен Евгений Степанищев (bolknote.ru):

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

Евгений Степанищев (bolknote.ru)
31 мая 2014, 10:51, ответ предназначен Efendy

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

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)