Как стать автором
Обновить

Комментарии 110

На самом деле это критическая ошибка в дизайне языка, так как ее нельзя исправить без потери обратной совместимости. Если в PHP6 забьют на нее (совместимость с PHP5), то может и поправят… Хотя учитывая их нацеленность на интерпрайзы, сложно себе это представить.
Иногда мне кажется, что php по сути — это критическая ошибка в дизайне языка.
А что вы хотите от языка, который писался студентами на коленке с целью сделать страничку слегка динамической? Усилиями Zend что-то более-менее серьезное получается.
да проблема в том, что с тех пор мало что изменилось. От named parameters в PHP6 отказались, по причине «мы этого не хотим». Зато в списках задач есть отдельным пунктом«speed up @-operator»… типа нафиг named parameters, используйте лучше @
Named parameters are not used in languages like C, C++, and Java. PHP позиционируется как C++ -like и Java-like, может быть поэтому? Но почему они тогда lambda-функции добавили?

А вообще, когда у вас много параметров, можно использовать хеши, а если нужно четко определить эти параметры, помогут value object'ы.
лямбда функции добавили, потому как в данном случае реализация вышла «без потерь», лямбда функции на самом деле банально обьекты, поэтому их можно было добавить в язык без лишних телодвижений.
угу, цитаты от автора языка:

There are people who actually like programming. I don't understand why they like programming.

I actually hate programming, but I love solving problems.

I don't know how to stop it, there was never any intent to write a programming language [...] I have absolutely no idea how to write a programming language, I just kept adding the next logical step on the way.

en.wikiquote.org/wiki/Rasmus_Lerdorf

Почитал цитаты Расмуса — многое стало понятно: процедурный стиль, сложности с ООП…
Ок, а какие альтернативы?
Из массовых, которые теснят php уже сейчас — python и ruby; через пару лет, возможно, javascript подтянется до схожего уровня удобства и инфраструктуры (хотя там тоже вопросов хватает); есть, наверное, еще куча менее массовых штук в этой нише + смежные вроде ASP.net.
Тем не менее, Джаваскрипт получился очень даже хорош.
Согласен, поэтому его и упоминаю. Косяков там хватает, но жить с ними вполне можно, да и функциональщина javascript очень выручает.
Эм, про PHP и нацеленность на энтерпрайз вы так странно пошутили, да?
Вот поэтому я всегда (и не только в PHP) аккуратно расставляю скобочки — и в тернарных операторах, и в остальных условиях. Просто во избежание разночтений. Да и читаемость повышается.

Фактически ваша фраза — смысл всего топика. Ставьте скобки, чтобы не было сюрпризов.
НЛО прилетело и опубликовало эту надпись здесь
В perl стараюсь не использовать скобки, для спорных/трудных случаев перед носом висит perlcheat sheet.
Очень уж засоряют скобки понимание — писать легко, а потом разбирать трудно. Проще сразу писать так, что бы было понятно, что имел в виду автор.
Автор явно претендует на приз «самый обфусцированный код». Задумайтесь, как будут читать код, сплошь состоящий из таких вот тернарников люди, а не интерпретаторы? Все тоже в меру хорошо, а вот такая простыня только усложнит процесс дебага в случае чего.
Вам код
value = isCondFirst()  ? valueFirst()  :
        isCondSecond() ? valueSecond() :
        isCondThird()  ? valueThird()  :
                         valueDefault(); 

менее понятен, чем?:

if (isCondFirst()) {
	value = valueFirst();
} else if (isCondSecond()) {
	value = valueSecond();
} else if (isCondThird()) {
	value = valueThird();
} else {
	value = valueDefault();
}
На его понимание требуется в несколько раз больше времени. В первую очередь на то, чтобы понять, в какой же, чёрт подери, последовательности выполняются тернарные операторы и не зарыта ли где-нибудь злая скобка, кардинально меняющая эту последовательность.
Везде, кроме php, порядок выполнения тернарного оператора совершенно очевиден и аналогичен порядку if-else.
Изменять и дополнять данный код проще чем ваш.
Кому как, мне вот к примеру более понятен код со скобками (о которых говорили уже выше)
$value = isCondFirst() ? valueFirst() 
                       : ( 
                            isCondSecond() ? valueSecond() 
                                           : (
                                                isCondThird() ? valueThird() : valueDefault() 
                                             ) 
                         );

Да, не так изящно, зато за счет скобок сразу видно логику выполнения и не важно заучил ли ты или тот, кого ты возможно даже не знаешь и который будет читать твой код, вот эту табличку.
А для тех, кто минусует, могу предложить такой вариант табуляции. Хуже ли он?
$value = isCondFirst()  ? valueFirst()  :(
         isCondSecond() ? valueSecond() :(
         isCondThird()  ? valueThird()  :
                          valueDefault() )); 
Ну в php или такой вариант или вообще без тернарного оператора. А в других языках лучше без лишних скобочек, имхо)
После python уж очень неказисто смотрится такое обилие скобок.
После питона, по-моему, любая скобка может смотреться лишней )
Именно так :) Сейчас пришлось вернуться к PHP и постоянно ловлю себя на этой мысли.
Грустные смайлики говорят, что им не нравится этот код :)
Вам понятен, а мне нет, по крайней мере с первого взгляда (в отличии от варианта с if'ми).

Такой код сложнее поддерживать, дебажить, изменять, что в нем может быть хорошего?
Вариант с If-ами мне тоже понятен. И вариант со скобками и вариант с if-ами гарантируют правильную последовательность обработки выражений, не требующую заучивания вышеуказанной таблицы. Поэтому поддерживать такой код все же лечгке, нежели код с тернарными операторами без скобок. И да — посмотрите мой второй комментарий с другой табуляцией.
Безусловно, такой код легче поддерживать чем код с тернарными операторами без скобок, но он все равно остается более тяжелым для понимания(дебага, изменения), по сравнению с if/else вариантом.
Спасибо за аргументированный интеллектуальный комментарий.
В таком виде совсем ничего не понятно.
код не менее понятен, а менее понятно зачем использовать ТАК этот оператор?

It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:

www.php.net/manual/en/language.operators.comparison.php
php — это исключение в силу костыльности.
А за исследование спасибо. :)
Я записываю так:

if      (isCondFirst())  value = valueFirst();
else if (isCondSecond()) value = valueSecond();
else if (isCondThird())  value = valueThird();
else                     value = valueDefault();

Читается не хуже варианта с ?:
Еще, как вариант можно записать так:
switch(true){
    case isCondFirst():
        value = valueFirst();
        break;
    case isCondSecond():
        value = valueSecond();
        break;
    case isCondThird():
        value = valueThird();
        break;
    default:
        value = valueDefault()
}
В С/С++ получаем ошибку: «error: case label does not reduce to an integer constant» для С и «error: a function call cannot appear in a constant-expression» для С++.
Пробовалось под gcc 4.8.2 как для C99 стандарта, так и С11

А вот в php хорошо работает :)
Это удобно, пока Вам не приспичит изменить код так, чтобы выполнить не одну функцию, а например две. Тогда весь кусок перекраивать придется. Во втором варианте стиль не меняется, а просто дописывается еще один вызов. Очень помогает, когда хочется быстро вставить печать отладочного сообщения (а то и по одному в каждой скобке, чтоб понять условие ветвления), а потом так же быстро его удалить.
$ php -r «print true? 1: true? 2: true? 3: true? 4: 5;»
5

Все-таки 4, а не 5.
Да, спасибо. Во время оформления допустил опечатку.
есть куда более изящные способы улучшить этот код. Использовать такую конструкцию — ад.
Какую именно конструкцию и какие способы улучшить код? Поменять язык? ;)
всё решает средствами php, головы и рефакторинга. Почитайте Фаулера на досуге, там примеры как такое преобразовать шикарнейшие
в С++ результат будет 1
Чёрт, тоже опечатка, спасибо.
Стараюсь ставить скобки (не php, objective-c), посе того: как мы с компилятором разошлись во мнения относительно этой конструкции:
10 + false?1:2
он расценил это как "(10 + false)?1:2" ? ;)
Я знаю об этом интересном нюансе довольно давно (…) В общем PHP себя снова показал «с лучшей стороны», но проблема далеко не критическая. Главное — знать про неё и быть осторожным с тернарным оператором в PHP.
Прочитайте уже, наконец, мануал по языку.

Довольно давно он знает.

Глава «PHP operators» находится вначале мануала. Там английским по белому все эти проблемы расписаны и даже сказано следующее: «It is recommended that you avoid «stacking» ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious»
Я даже процитировал мануал в топике.
Тогда я не понимаю, почему вы считаете, что PHP показал себя не с лучшей стороны. Напротив, он честно признаётся, что поведение не лучшее и советует вообще не использовать этот случай.

Такое честное отношение к проблеме — редкость.

Ну и, кроме того, никакой проблемы бы не было, если бы программисты давали себе труд хоть раз прочитать мануал.
Ну, все баги от недостаточного чтения мануала. Фактически ни один технический топик на Хабре не нужен, так как всё описано в мануалах.
Тем не менее, большинство этого нюанса не знает и потому могут допустить ошибки.
Вашу заслугу я отрицать не могу — действительно многие мануалов не читают. За это спасибо. Но мне кажется, что воспитательный момент должен быть другим. Не «PHP — дерьмо», а «читайте мануал, не полагайтесь на знания, полученные из других языков».

Ну и вы не правы. Тут очень много новостей, статей, где рассматриваются новые техники или подводные камни, которые не описаны в мануалах.
Согласен, с статьями на Хабре я, возможно, немного утрировал.
Я бы предпочёл сделать оба названных вывода ;) Согласитесь, что это не совсем корректно — при одинаковой сути и записи (вплоть до символа) оператора — совершенно различное поведение, в т.ч. в сравнении с языками, на которые он старается быть похожим.
Не-а, не соглашусь.

Вспомните как выглядит «if» в разных языка программирования, к примеру. Конструкции могут нести разный смысл, это нормально. У языков разный путь. Где-то «def» задаёт функцию, где-то — переменную.

А на какие языки, по-вашему, PHP хочет быть похож?
В 1994 году датский программист Расмус Лердорф создал набор скриптов на Perl/CGI для вывода и учёта посетителей его онлайн-резюме, обрабатывающий шаблоны HTML-документов. Лердорф назвал набор Personal Home Page (Личная Домашняя Страница). Вскоре функциональности и быстроты Perl — интерпретатора скриптов — перестало хватать, и Лердорф разработал с использованием языка C новый интерпретатор шаблонов PHP/FI (англ. Personal Home Page / Forms Interpreter — «Личная Домашняя Страница / Интерпретатор форм»).


Синтаксис PHP подобен синтаксису языка Си. Некоторые элементы, такие как ассоциативные массивы и цикл foreach, заимствованы из Perl.

Очевидно, что в то время Расмус программировал на C, Perl и хотел создать простой язык с похожим синтаксисом. Вот только его, видимо, подвело непонимание того, как в этих (да и в других, что уж говорить, почти во всех) языках работает тенарный оператор. И из-за этого маленького косячка разработчики на PHP страдают (слегка преувеличил, но все же) на протяжении уже 15 лет…

Да, и это можно расценивать как фишку языка. Но на самом деле это всего лишь результат безответственности создателя.
Не факт, что в PHP2 был тернарный оператор, я на нём не программировал, так что не могу знать. Не факт, что был вложенный тернарный оператор. Так что на авторе PHP/FI, возможно, вины и нет.
С чего Вы взяли, что он не понимал поведение тернарного оператора в Си и Perl?! И почему это косячок с его стороны? Он сделал php для себя, как свой личный инструмент, и, возможно, намеренно сделал тернарный оператор с другой ассоциатичностью.
Если бы он делал только для себя, мы бы сейчас им не пользовались. Хотя, можно допустить, что тенарник привнес кто-то другой, а ответственные лица просто не проконтролировали (и поэтому тоже виноваты). Тенарный оператор — это классическая конструкция, общая для всех языков, идеологически повлиявших на PHP. Разве вы видите другие причины, кроме невежества дизайнеров языка, которые повлекли за собой подобную реализацию?
тернарный, извините =))
Да ладно вам, TheShock и опциональные параметры не любит в JS. Опять же по причине нежелания читать докуметацию по API языка.
Тро-ло-ло.
Ваше трололо уже достало. Если самому нестыдно от своей безграмотности, то хотя бы постарайтесь читающих вас не вводить в заблуждение.
Нет, просто достал уже троллинг ваш постоянный. А, иногда, и полная оторванность от вопроса. Мне вот интересно, у вас вообще есть какие-то проекты, вы пользуетесь тем, о чём рассказываете, или вы просто теоретик, который иногда несёт бред в комментариях?
То есть замечание о том, что вы не знаете даже обязательных параметров функций в JS — это троллинг? Ну, извините… В таком случае я действительно полнейший теоретик, ибо на практике таких товарищей приходится увольнять нафиг.
Весь смысл топика можно уместить в двух предложениях:

Будьте осторожны при применении в PHP привычек, выработанных на других языках! Например, тернарный оператор в нём выполняется справа налево, в отличие от C, EcmaScript, Java, Perl, Python и Ruby.

А это ваше «только до следующего оператора» просто ошибочно.
Нет, вы ошибаетесь. Тернарный оператор выполняется слева направо. Но не так, как в других языках.
Это доказал код в статье и цитата из мануала.
Странно, мне ваш код доказывает именно выполнение справа налево. Вот посмотрите на этот кусок своего кода:
(
	(
		cond.first() ?
			value.first() :
			cond.second()
	) ?
		value.second() :
		cond.third()
) ?
	value.third() :
	value.default();


Последовательность действий такова:
  1. Видим выражение из трёх «?:».
  2. Выбираем самый правый (третий), и начинаем его вычислять.
  3. Вычисляем условие (третьего «?:»).
    1. Видим выражение из двух «?:».
    2. Выбираем самый правый (второй), и начинаем его вычислять.
    3. Вычисляем условие (второго «?:»).
      1. Видим выражение «?:» (первое).
      2. Вычисляем условие (первого «?:»; пишется cond.first).
      3. Истина, вычисляем выражение_если_истина (первого «?:») — first (пишется value.first) — и возвращаем его.
    4. Истина, вычисляем выражение_если_истина (второго «?:») — second (пишется value.second) — и возвращаем его.
  4. Истина, вычисляем выражение_если_истина (третьего «?:») — third (пишется value.third) — и возвращаем его.

Результат — third. Может, что-то оригинальное и неочевидное (с точки зрения других языков) в этом есть, но всё же ничего удивительного.
Тю, сам запустался! Всё наоборот!
Я понял вашу идею. Кажется, вы таки правы.
Эх, есть всё-таки у меня дар запутываться самому и убеждать в этом других. Предыдущий комментарий верен только частично, извините.
Я согласен с тем, что моё «только до следующего оператора» — бред.
Последовательность действий в предыдущем моём комментарии описана верно, но обоснование совсем другое — выполнение слева направо означает, что операторы заканчивают выполняться слева направо.
Что такое «оператор выполняется слева направо» или «справа налево», можно понять из следующих формул:

слева направо: a * b * c = (a * b) * c
справа налево: a * b * c = a * (b * c)
НЛО прилетело и опубликовало эту надпись здесь
Извините, сам запутался. Распутываюсь.

Весь смысл топика можно уместить в двух предложениях:

Будьте осторожны при применении в PHP привычек, выработанных на других языках! Например, тернарный оператор в нём выполняется слева направо, в отличие от C, EcmaScript, Java, Perl, Python и Ruby, в которых он выполняется справа налево.

А это ваше «только до следующего оператора» просто ошибочно.
Как хорошо что я никогда стараюсь не писать более 3-4 операторов в одном выражении и максимально подчеркиваю приоритет операцию скобками, пусть зачастую и излишне…

Автор, спасибо! Очередной аргумент против PHP. Больше всего меня умиляют заявления похапешников в стиле «это не проблема языка, просто мануалы читать надо». Такое ощущение, что фраза «программировать надо не на языке, а с помощью языка» похапешниками упорно отрицается и не воспринимается в серьез:/
НЛО прилетело и опубликовало эту надпись здесь
Зависит от задачи. Для утилит командной строки вполне подойдет и Perl, и Python. Для создания сайтов вообще куча языков есть. Для создания демонов — тоже. Оконные приложения создавать на PHP — просто издевательство. Продолжать?

PHP очень легко изучать. Поэтому он и популярен среди новичков. Но это не значит что сам язык хороший. Плохое проектирование языка создает относительные проблемы с отладкой и поддержкой. А еще есть фактор низкой производительности (опыт Facebook'a похапешников не навел на соответствующие мысли?), та же Java во много раз быстрее работает.

Вообще, часто PHP сравнивается с Python'ом. Последний я, к сожалению, не знаю. Зато помню насколько комфортнее мне стало работать, когда я перешел с PHP на Java. Безусловно, и там есть свои минусы, но кол-во мыслей «какой идиот это создавал?!» во много раз меньше.
PHP — единственный язык который создавался для написания сайтов, помните об этом
и никакие сравнения с фреймворками не годятся, тем более что сами эти фреймворки архитектурно ущербны с точки зрения вебдева

с другой стороны вы передёргиваете фразу «писать надо не на языке а с помощью языка» до «я буду говорить по английски, но слова ставить как в русском, мне так удобно и так делают все кого я знаю»
эта фраза заключает в себе то что писать код выпасывающий фичи языка и приводящий его в благочитабельный вид занятие неблагодарное(привет рельсам), а не то что все языки должны работать одинаково
Неважно что для чего создавалось. Важно что есть сейчас. А если PHP такой особенный, то почему большинство последних нововведений как в языке, так и в PHP фреймворках повторяют других языки, ту же Java, например?

Если спускаться до конкретики, то давайте вспомним такое понятие из usability как user experience. Имхо, это понятие и для языков программирования вполне применимо.

Язык не должен мешать. А тот же тернарный оператор, работающий отличным образом от всех других популярных языков, мешает. Можно привести и другие примеры. Если новичку в программировании еще можно сказать «учи мануалы», то человеку с >10 лет опыта, например, С++ вы тоже такое же скажите?

Да, PHP хорош для быстрого создания относительно простых сайтов. Да, он хорош для изучения новичками. Да, он хорош своей простотой. Но программист, знающий только PHP не может быть хорошим программистом.
Вам, простите, тернарный оператор в каком месте мешает то?

Что вы понимаете под «знающий только»?
НЛО прилетело и опубликовало эту надпись здесь
Хороший программист в моем понимании — это уровень лида или архитектора. PHP, как язык, очень ограничен в возможностях. Следовательно, у лида на PHP меньше выбор. У него меньше кругозор.

Посмотрите на современные PHP фреймворки. Тот же Symfony. Все те новинки, фичи, что там есть, много-много лет назад уже во всю использовались в мире Java. В PHP о том же самом DI, IoC, ORM, AOP и т.д. начали говорить совсем недавно, почему?

И вообще, причем тут девушки? Странное сравнение. PHP — такой же инструмент для разработчика, как и молоток для строителя. Инструмент, даже такой простой как молоток, может быть плохим. И это нормально. И совершенно нормально осознавать эти минусы и говорить о них. А вот не заниматься самообучением для разработчика ненормально. Ибо знания такого разработчика очень быстро теряют актуальность.

И ладно бы просто писал «PHP — говно», но, нет, я пытаюсь аргументировать свою точку зрения и готов к обсуждению. Так что давайте не будем кидаться словами аля «хаять», пожалуйста. И, да, я прекрасно понимаю в чем PHP хорош. И с точки зрения разработчика, и с точки зрения платящего ему деньги. В конце-концов, сейчас я пишу на двух языках — на Java и на PHP.
и в чём же вы чуствуете ограниченность РНР?
о 5.3 конечно же речь идёт

В PHP о том же самом DI, IoC, ORM, AOP и т.д. начали говорить совсем недавно, почему?
говорили давно, сейчас стали говорить громче и вы наконец то услышали
а громче стали говорить из за того что это стало более востребованным и появились достойные библиотеки
НЛО прилетело и опубликовало эту надпись здесь
а программист упорно доказывающий что язык N == уг — не программист

и да, если сам Страуструп полезет в PHP не читая манов и будет задавать глупые вопросы — я пошлю его в доку

у РНР есть своя прелесть, для генерации веб страниц пока что ничего лучше не придумали, а что нововведения «аля джава» — это детский лепет, в джаву эти штуки тоже пришли из других языков
НЛО прилетело и опубликовало эту надпись здесь
Алексей, вы в своём репертуаре.
Намёк 1:
echo 3? 4: 5;

Намёк 2:
function huy($v){
echo $v;
}
echo true? huy(1): true? huy(2): true? huy(3): true? huy(4): huy(5);

Намёк 3:
function huy($v){
echo $v;
return $v;
}
echo true? huy(1): true? huy(2): true? huy(3): true? huy(4): huy(5);

PS: Должно быть достаточно, чтобы отдуплить, что порядок выполнения тут не причём.
Автоматическое преобразование типов (в данном случае из числа в булевое) и проверка с ==, а не ===
Без скобочек, говорите? В 1с от этого избавились так:

a = ?(true,1,?(true,2,?(true,3,?(true,4,5))));


Как это можно изобразить без if — elseif просто для понимания — непонятно…
Всё такие я полностью согласен с комментарием от cblp. Проблема не в том, что «PHP мыслит оригинально. Каждый тернарный оператор распростаняется не на всё выражение, а только до следующего оператора.»(такая формулировка вообще не верна), а в том что в мануле php написано
php_man_ternary
где Left associativity means that the expression is evaluated from left to right
В то время, книга по Си от Kernighan&Ritchie нам говорит совсем противоположное:
c_book_ternary
Значит надо ожидать в точности противоположного резльтата при приминении этого оператора в PHP и С.
Более интересный, на мой взгляд. вопрос, почему в PHP, позиционирующем себя как C-подобный, ассоциативность тернарного оператора отличается.
«Всегда пишите код так, будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете» (с) Martin Golding

print true ? 1 : true ? 2 : true ? 3 : true ? 4 : 5

В нашей команде такое не приветствуется и даже запрещено code-style.
я бы даже предложил отрубать руки, например
И пересаживать в плечи.
Нравятся мне такие задачки. Не подскажете, где ещё подобные можно найти?
на практике, с давних давен, вместо тернарника использую:
cond_1() and $a = value1() 
or cond_2a() and cond_2b() and $a = value2() 
or cond_3() and $a = value3() 
or $a = value4();


на мой вгляд, нагляднее и позволяет создавать группу команд аля «транзакция». применимо исключительно к php из-за его значимости операторов and/or
Мне вот интересно — а если условий станет 10? :) а 20?
На практике такое не приемлемо, но вот в теории?
разумно надо подходить к делу, а не использовать метод ради выпендрежа. в данном случае это короткое if разветвление для определения переменной.
да даже хотя на одно условие больше нужно будет добавить — уже приплыли
та нет, легко. отличий между if ( cond() && cond2() ) и cond() and cond2() никаких.
В соот-щем разделе документации языка PHP, посвященном тернарному оператору — однозначно сказано что вложенность ему противопоказана, и порядок выполнения оных без скобок вполне может в один прекрасный момент измениться. А как известно — то что задокументировано — уже не баг.
$a = true ?: false; // true

$a = false ?: true; // true

$a = 1 ?: 2; // 1

$a = 0 ?: 2; // 2
Тут логично всё)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории