И и И (логические выражения в 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.
Впрочем, я такой способ программирования крайне не рекомендую — для современных программистов он сложен.
Я кстати, пользуюсь «набором из бейсика», поскольку по диагонали оно читается в коде на порядки легче. Приоритеты скобками задаю всегда — ИДЕ подсвечивают, позволяя разбирать довольно сложные условия.
Не знаю, хорошо это или плохо, просто так привык. :)
Комментарий для Горбунов Олег:
Это вопрос привычки. Одни значки и другие значки.
Плохо. Не нужно лишнего, это как ударения в каждом слове расставлять — больше знаком без какого-либо смысла. А в случае конструкций это просто не работает: http://bolknote.ru/all/4143
Отлично, отлично :)
смешно конечно, но вообще зачем так усложнять код? по мне так проще написать в три строчки. через три года будет проще разбираться почему не работает :).
Я ещё со времён Бейсика (то есть, чуть меньше последних 25 лет) всегда расставляю скобки в логических выражениях и вокруг тернарного оператора. Вне зависимости от того, на каком языке пишу. Это правило как раз снимает необходимость помнить, в каком языке какие приоритеты.
А вещи типа
вообще стараюсь не использовать. Мало ли, вдруг сам не пойму, что я тут имел в виду, через пару лет копаясь в старом коде.
Комментарий для hshhhhh.name:
Самое смешное, что никакого переусложнения нет. Это очень простое выражение. Но современные программисты считают его сложным.
Комментарий для PastorGL:
Это вопрос владения языком. Современный подход подразумевает, что лучше иметь низкий уровень в куче языков, чем идеально знать 1—2.
Комментарий для Евгения Степанищева:
Я не считаю его сложным, но просто из-за того что я and/or не пользовался уже много лет я не сразу найду ошибку / пойму как оно работает.
То есть я всегда знал что там разные приоритеты и да, глаз у меня за это зацепиться, но мне будет нужно лезть в доку.
Тут дело не в современном подходе, а в современных реалиах. Вот знаешь ты сейчас, например, идеально пхп, а интересную работу найти совсем не так просто как 5 лет назад.
А на C что 10 лет назад, что 20 -- можно было найти работу.
Вопрос в мимолётности языков.
Ну и самая большая проблема в том что сейчас люди не учат языки программирования -- люди изучают фреймворки к языкам программирования.
Типа в требованиях редко можно найти Ruby/Python, но почти всегда Ruby On Rails / Django.
В современом мире работодателю редко нужны люди которые зачем-то помнят приоритеты для and / or если ими не пользуются %)
Комментарий для hshhhhh.name:
Работодатель тут не причём. Это вопрос профессионализма. Именно поэтому я могу найти любую ошибку в чужом коде (при этом я не программистом работаю), а из кучи программистов вокруг — считанные единицы.
Комментарий для Евгения Степанищева:
Найти ошибку это одно.
Я про то что в пхп достаточно большое колличество вещей не совсем очевидно и в них надо вникать и разбираться. Эти вот приоритеты или нюансы с кастованием.
Я считаю что знать про них надо, но при этом я не совсем понимаю зачем писать код в котором могут быть ошибки.
То есть привёденный пример в статье: $ret_logic = $criteria or CheckSomething();
На мой взгляд совсем не пример хакерского кода, а кода плохого.
в чем проблема записать это в две строки?
$ret_logic = $criteria;
$criteria || CheckSometing();
Я бы ещё и в иф обернул просто потому что в пхп так писать не принято. На мой взгляд это такое же хакерский код как и писать if () без фигурных скобок. Можно -- да. Зачем? Непонятно.
Комментарий для Евгения Степанищева:
Если писать этот «хакерский код» как прототип с целью склепать на коленке что-то быстрое и важна скорость -- да, конечно.
В реальной жизни в любом коде должны быть такое дикое колличество проверок, то экономия одной строчки (и усложнение логики) не влияет ни на что. Я не понимаю зачем :).
Комментарий для Евгения Степанищева:
Опять же если рассматривать их как радость от познания возможностей компилятора -- да сам бог велел.
Но вот, например, в пхп есть анонимные функции. Анонимные функции это очень круто. Только в пхп ими практически не пользуются, но ведь они есть. Почему ими не пользуются?
ну да, раньше и трава была зеленее и программисты лучше.
Комментарий для hshhhhh.name:
Нет, это не он. Просто внутри некоторых языков программирования тоже появляется «мейнстрим». В ПХП это можно назвать «пишем на детсадовском в Си» (без указателей и прочих прелестей Си).
Пользуются. Только не те, кто клепает маленькие сайты — во-первых, там всё равно как писать, во-вторых, хостеры лениво обновляются. Те, кто делает код, который требует выделенный хостинг, используют все прелести новых версий — это просто очень удобно.
Комментарий для zg.livejournal.com:
Я уже более 15 лет нанимаю программистов. Вижу куда движется всё.
Комментарий для Евгения Степанищева:
это очень маленький срез.
не очень понятно, как по такому маленькому срезу можно прямо таки видеть всё.
Комментарий для zg.livejournal.com:
Это нормальный срез.
Во многих языках приоритет у && и and разный, но такой нюанс как у тебя в примере — это изобретение пхп и оно не логично
почему вы так решили?
Комментарий для Efendy:
Если разный (а где, кстати, такое ещё есть?), то это не изобретение ПХП, а работает так же везде или схожим образом, так как пример и строится на разнице приоритетов.
Комментарий для zg.livejournal.com:
А почему вы так решили? Я ответил одним голословным утверждением на другое.
А еще есть редко упоминаемый оператор «<>», синоним «!=». Насколько помню, приоритеты у них одинаковые.
Комментарий для anothersite.ru:
Да, они полные эквиваленты. Я когда-то в ПХП пользовался только <>.
Комментарий для Евгения Степанищева:
Такая же ботва в Руби: http://www.techotopia.com/index.php/Ruby_Operator_Precedence
Частенько использую их в стиле
redirect_to ’xxx’ and return
check_something or raise some_exception
Комментарий для Илья:
Надо же! Ещё и приоритеты примерно как в ПХП.
Комментарий для Евгения Степанищева:
Да, и такая же проблема с присваиванием и вообще. Поэтому очень быстро отучаешься использовать в сложных случаях, так как почти всегда оно работает не так, как ожидаешь. Фактически, только как в примере выше и использую, удобно — емко, кратко, вместе с тем читабельно.
Комментарий для Евгения Степанищева:
В perl разный приоритет, вот первое что выдал гугл http://hscripts.com/tutorials/perl/operators/oprpreced.php
Комментарий для Efendy:
Странно, что Перл в голову мне не пришёл.