Pull to refresh

Comments 316

Произойти должно не это. Авторы должны посмотреть как используют их язык и сделать все возможное что бы облегчить его использование. А сейчас в тренде у нас, например, аннотации, ради которых приходится парсить комментарии. Но конечно же, зачем думать как сделать нормальным данный механизм, сообщество еще пять лет будет одним глазом в доку смотреть, другим в код — это же так удобно. Они лучше пропуск параметров запилят
Нельзя сказать, что не смотрят на использование. Свойства вон добавляют. А то меня каждый раз передёргивает, когда ради свойств я парсю строчки.
Свойства это дальнейшее развитие __get/__set которым уже много-много лет. А «аннотации» появились недавно — по сути команда доктрины второй их перетащила в язык
«Магические» методы, оперирующие на строчках — это кривые костыли, и ничего более. Это не развитие, а переосмысление.
Вот не прошло и десяти лет, как они это поняли. Слишком медленно до них доходит, что клевые фишки облечающие написание кода надо обязательно тащить из других языков и делать не менее круто.
Тогда непонятно, зачем столько негодования и рассказов, что авторы языка должны делать.
Может потому, что данный язык не так давно был моим основным и мне интересно дальнейшее его развитие даже не смотря на то, что я вряд-ли когда-нибудь к нему вернусь?
Вам просто интересно развитие, а нам на нём писать. Но вы указываете авторам что они должны делать для себя и для нас. Напоминает позицию эмигрантов, из-за границы указывающих как нам тут жить. Нормально?
Ага, это уже давняя мечта. С того момента, как увидел это в питоне.
После этого всего останется добавить строгую типизацию и приделать компилятор =)
Ну зачем же писать самим, генерить байткод для jvm и llvm
Чем не устраивают существующие кэши опкода или хипхоп?
В хипхопе очень много проблем, в нем развивают только те фичи, которые нужны Facebook.

Если, допустим, затачивать новый проект конкретно под хипхоп — еще вариант, то с компиляцией старых больших проектов, так сказать, пичалька.
А вы думаете, что в случае появления нативной компиляции и статической типизации старые большие проекты не придётся переписывать?
Статическая типизация может быть необязательной. По дефолту тип а-ля variant, а указал конкретно integer или string будь добр соответствовать. Такой опыт уже есть с var vs public/protected/private или тем же typ hinting.
Ммм, компилировал ряд больших старых проектов хипхопом, не умер.
Из проблем только то, что пришлось ряд расширений PHP портировать под хипхоп (и что сторонние расширения хипхоп без плясок не подключает). В остальном никаких проблем. Каких фич не хватает?
ЕМНИП, даже его в специальном режиме можно включить.
type hinting для всех типов данных решит, имхо, бОльшую часть проблем, которую решает статическая типизация.
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) { ... }

Нет никакого способа установить $report_errors = false без повторения двух других значений по умолчанию. Для решения этой проблемы предлагается использовать пропуск параметров:

create_query("deleted=0", "name", default, default, false);


Думаю, не сильно этот синтаксис поможет.

Сделали бы уже как в питоне create_query("deleted=0", "name", $report_errors=false);, было бы круто.
Именно так — нельзя, так как будет конфликтовать с текущим поведением. Скорее уж как-то так:
 create_query("deleted=0", "name", "report_errors"=>false)
И в случае переименовывания параметров этого метода придется переписывать весь код, который его использовал? На фиг… «default» в этом плане гораздо нагляднее.
Если меняется api, то код тоже, скорее всего, поменяется
Может поменяться только имя параметра.
UFO just landed and posted this here
UFO just landed and posted this here
Почему в рамкать рефакторинга может поменяться имя переменной в заголовке, но не может поменятся название метода?
Всё, что внутри метода относится к внутренней реализации и внешний код не должно волновать как называется параметр функции — $cnt или $totalPages.

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

В общем, для лучшей внутренней читаемости кода может потребоваться переименование внутренней реализации. Тем кто использует этот API снаружи вообще должно быть до лампочки до начинки.
«Внутри метода» для меня начинается со знака { в Си-подобных языках. И мя параметра это интерфейс прежде всего, даже если он средой исполнения никак не контролируется. Если возникла необходимость переименовать реализацию, то просто сделайте первой строкой в теле метода $new_name = $old_name. А вот изменение имени параметра (части интерфейса) должно свидетельствовать об изменении поведения.
Всё, что внутри метода относится к внутренней реализации и внешний код не должно волновать как называется параметр функции — $cnt или $totalPages.

Это кто вам такое сказал? Есть куча языков и фреймворков, которые подтверждают ошибочность ваших слов.
А причём тут «куча языков»? Мы же про PHP говорим.

И потом, отнюдь не куча. В большинстве языков имеет значение именно порядок параметров и/или их тип. Но никак не названия.
В случае переименования функции тоже придётся переписывать код.
И вариант с именованными параметрами куда удобнее чем передавать массив типа $options, у которого неизвестно какие ключи.
Если переменные назвать сразу правильно и к месту, то переименовывать не придётся, а если и возникнет вдруг такая необходимость, то в нормальных средах есть рефакторинг кода.

Я только за введение именованных параметров:)
> И вариант с именованными параметрами куда удобнее чем передавать массив типа $options, у которого неизвестно какие ключи.

В качестве ключей можно использовать константы класса (многословно, да). Да и потом, тут многие пишут «20 параметров слишком много», какой смысл этой «фичи» при 4-5 параметрах? Никакого.

А насчет рефакторинга — не все IDE его поддерживают (привет PDT), к сожадению. Да и изменить только название метода гораздо быстрее и проще чем проверять и изменять еще и его аргументы (имена которых, ИМХО, вообще относятся к внутренней реализации метода и не должны никаким образом влиять на вызывающий код).
Вопрос только в том, что считать сигнатурой, то есть интерфейсом функции/метода.
Возможен компромисс вида:
create_query("deleted=0", "name", $report_errors=>false)

Как некое подобие передачи через массив
create_query("deleted=0", "name", array($report_errors=>false))
или
create_query("deleted=0", "name", [$report_errors=>false])
Через массив вообще не вариант, как тогда массив передавать?
Через массив было бы уместно опять же со спец-синтаксисом — как в Python'е или других языках — через ** или ему подобное. Но поскольку всё упирается в шаманство с парсером — вряд ли мы увидим оптимальные варианты…
Точно так же сейчас можно сказать, что если поменять порядок аргументов функции, то весь тоже придётся переписывать.
А я предложил бы просто ставить запятые без параметров:
create_query("deleted=0", "name", , , false);

Таким образом работает, например, цикл for. Сразу видно, сколько параметров, в каком порядке идут, и при рефакторинге если сменится имя входящего параметра функции — не будет никаких проблем.
Ваш вариант лучше предложенного, но тоже ужасен. Не должно быть методов с 20-ю аргументами, потому что такой код невозможно читать, не вызывая справку на каждой строчке.
Но что если такая функция уже есть, как встроенная?
Легче когда передаётся один-единственный массив, ключи которого вообще никак (средствами языка, и даже сторонними типа phpdoc) не документируются? Легче вместо «лезть в справку» (а хорошая IDE подсветит сигнатуру автоматом) лезть в тело и полностью его анализировать?
Мне тоже кажется это самым логичным синтаксисом. Очень давно такого не хватало.

Когда-то давно, когда первый раз возникла необходимость оставить не_последний параметр в значении по-умолчанию, я именно такой синтаксис и использовал. И убедился, что он не работает :)
Сможете закинуть с рассылку internals?
отличная мысль, гораздо лучше default, тем более, что в list() такое уже используется

На сколько я знаю, сейчас это можно сделать просто указав значение пропускаемого параметра, как NULL, и оно примет значение по умолчанию:
create_query("deleted=0", "name", NULL, NULL, false);
Если в функции это реализовано вручную, то да. А так нет.

function some($arg1, $arg2 = 'some', $arg3 = 5)
    {
    echo $arg1 . ' ' . gettype($arg1) . PHP_EOL; // 1.1 double
    echo $arg2 . ' ' . gettype($arg2) . PHP_EOL; // NULL
    echo $arg3 . ' ' . gettype($arg3) . PHP_EOL; // 100 integer
    }
some(1.1, null, 100);
UFO just landed and posted this here
Можно, но в 99.9999% не нужно.
Reflection — очень, очень медленно в runtime. Уж лучше программист разок оторвет глазки и посмотрит документацию.
UFO just landed and posted this here
Хотя нет, я не прав, я внутри уже сам обрабатывал эти NULL, и преобразовывал в значения по умолчанию. Сорри а дезинформацию.
Нельзя — в метод будет передан null, а не значение по умолчанию.
Тоже хочу именованные аргументы…
UFO just landed and posted this here
А в VB это пишется так:
create_query("deleted=0", "name", , , false)

Но полагаю, что это не самый хороший вариант, так как можно случайно пропустить какойто параметр, а парсер на это даже ничего не скажет.
Давно мечтаю о таком варианте. А что бы ничего не пропускать, надо юзать IDE — они все это умеют.
Один комментарий не дочитал до вашего, выше написал такой же код)
Отуствие аннотаций в списке свидетельствует о том, что язык развивается сам по себе, а приложения пишутся сами по себе. Впрочем, как по мне, тут вина не столько разработчиков языка, сколько фреймворков предлагающих их использовать.

Понравились getters, setters, генераторы (привет руби) и FooBar::class (привет он же).

Но чего реально нет, каких-то нормальных механизмов задавать конфигурацию на PHP. Массвы себя изжили, а аннотации (в нынешнем виде) не могут быть отлажены никак кроме как в реалтайме.
И чем же массивы себя изжили? Не модно?
Тем же чем и аннотации — отуствие валидации. Т.е. правильность конфигурации не проверишь пока не запустишь приложение. Тем более не узнаешь, что неправильно написал конфигурацию кеша, пока твой сайт не упал под хабраэффектом.

Т.е. грубо говоря, хотелось, чтобы можно было задавать конфигурацию в соответствии со схемой.
И я не говорю, про XML. Я говорю, что сам язык должен иметь средства для задания такого рода конфигураций. Chained methods — как вариант. Но аннотации с интерфейсами были бы лучше.

И массивы изжили, да.
То есть, вместо того, что бы написать над классом, что у поля name должна быть минимальная и максимальная длинна, оно не может быть null, лучше создать еще один файл с описанием классов, полей и какие методы валидации использовать.

yaml хорош, но аннотации — это нечто другое. Это мегаудобная метаинформация которую я могу получить в райнайме у объекта без лишних проблем.
После года на симфони2 я ненавижу аннотации. Они мешают читать код.
Приведите пример мешающих читать код аннотаций.
У меня дискомфорт когда у свойства 8 строчек комментариев. А свойств бывает более 10. 100 строчек на свойства — излишек.
А когда эти свойства разнесены по нескольким разным файлам у вас дискомфорта видимо нет?
Мы, в яве, это пережили, несколько лет назад. На людей любящих xml, в котором раньше любой чих любили описывать и которого иногда было больше нежели самого кода, теперь смотрят косо.
YAML не XML. Гораздо проще и понятнее.
Да какая разница, хоть json/bson, хоть любимый бинарный формат.
Это не читаемо, потому что:
1. это лежит хрен знает где.
2. это лежит хрен знает где в хрен знает каком формате.
3. этот формат хреново описан и хреново поддерживается (если конечно не промышленный стандарт, но там другая пичалька)
4. это далеко от того места где я пишу код (иде мне не подскажет где я не прав) а с аннотациями — на раз
5. этих хреней может быть много
Если на уровне синтаксиса:
— определить где лежит (autoload)
— определить формат
— нормально документировать
— IDE будет понимать
-оставить единственное место

то у вас претензий не будет?
Ну и yaml нельзя валидировать по схеме. В этом XML выигрывает. Но он менее читабелен, это факт.
Кто запрещает мне валидировать yaml?
Отсутствие стандартной возможности задать схему валидации, кроме как соответствие синтаксису?
В мире EE из одной крайности в другую бросаются. Если вспомнить XML-ки того-же Hibernate, то они до занудства «правильные» и жутко избыточные. Впрочем, как и сам XML. С аннотациями, кстати, сильно лучше не стало (по крайней мере пока я ещё в теме был) потому как во-первых чтобы посмотреть на общую картину нужно было лезть в определённые классы, а во-вторых, конфиг, хоть и в аннотациях был не менее монстроподобным.
Да при любом раскладе лучше не станет, таков мир EE. Он странный, надутый и немного пугающий, сам по себе: смешно выглядит прописывание запросов на несколько строчек в аннотациях в качестве оптимизации запросов которые генерит ORM.

Общую картину на пару десятков (а то и сотен) сущностей думаю вряд-ли можно чем-нибудь посмотреть. Иногда даже схемы не спасение.
Вот собственно и пример того, что ни аннотации ни ямл не могут быть идеальным форматом конфигурации.
По мне так лучше задать этому полю value тип со всеми этими ограничениями. Возможно тип типа generic: IntegerInRange<1,5> вместо типа SchoolMark, описываемого отдельно.
Вообще-то что аннотации, что XML, что yaml — одно. Если вы не опишите правила по которым нужно валидировать конфигурацию, ничего валидироваться и не будет и, естественно, аннотации никаким боком не спасут ваше приложение от нагрузок, если вы в них прописали медленный бэкенд для кеша. Ровно как и массивы или yaml. Всё это — обёртка и к валидации отношения никакого не имеет.
Думаю тут под валидацией имелось в виду другое. Я думаю если бы можно было бы написать валидатор, который смог понимать при какой нагрузке что как использовать и пинал разработчика, то мы бы жили немного в другом мире.

Аннотация она часть кода — ее можно посмотреть, если поле объявлено как int, то туда не получиться запихнуть строку, а вот в конфиге yaml или xml — без правил пожалуйста, а проблема всплывет уже в рантайме.
если поле объявлено как int, то туда не получиться запихнуть строку,

Это называется статическая типизация, а не аннотации. Афаик, аннотации это не указания транслятору, это метаинформация для других частей проекта, которая корректно валидироваться может только в рантайме, по крайней мере для интерпретируемых языков со слабой типизацией, каковым является PHP.
Ну генераторы только в руби есть конечно же.
UFO just landed and posted this here
Асясяй? Какие грабли со свойствами в c#?
Какие грабли? В шарпе свойства реализованы офигительно. Отдельные уровни доступа, полиморфизм, вынесение в интерфейсы — всё есть.

Остальное — это уже культура программирования. Например, свойства при чтении должны возвращать только что записанное. Не быть тяжеловесными. Ну, то есть быть свойствами.
inteface ISample {
int Prop {get; set;}
int ReadOnlyProp {get;}
}

Свойства в c# это вообще образец удобства синтаксиса описания свойств. Жаль что в Java/AS3 «пошли своим путем». А в PHP я magic __get/__set принципиально не использую, хотя иногда проперти бы и пригодились, но проще уж через get/set методы, они хоть в автокомплите нормально всплывают. Лично я очень раз что в PHP потянули именно такой синтаксис свойств. Запилят — сразу начну использовать.
О, поколение, не видевшее Делфи…
Очень обрадует наличие Простого API для хеширования пароля
Не совсем понятно, как с солью? Это просто надежнее хеш без соли так? Тогда можно было еще параметр влепить для соли.
Соль, как я понял, автоматически добавляется. возможно, будет и отдельный метод для её генерации.
А чем конкатенация не угодила?
Влепили:

password_hash(string $password, int $algo, array $options = array()) — … The $options array allows for passing in algorithm specific options. In the case of bcrypt, two options are supported: salt and cost. The salt parameter, if provided, will be used in place of an auto-generated salt
auto-generated salt от чего зависит? Портируема ли между хостами?
По поводу пропуска параметров согласен, не удачный вариант.

Я бы предложил нечто такое:
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) {… }
И вызов:
$query = create_query('is_active=1', *5 = false);
Где любая конструкция начинающая с *[1, ...] будет расцениваться как не явный аргумент функции и интерпретироваться уже после того, как все аргументы проставлены.
Например:
$query = create_query('is_active=1', 'name ASC', *2 = 'country DESC');
Таким образом *2 = 'country DESC' оверайдит уже заданный второй аргумент 'name ASC'.
Извиняюсь, тэги не подцепились.
Лучше уж тогда именованные, чтобы было видно, что присваиваешь. А так не только нужно порядок помнить, но и рефакторить невозможно простым поиском имени по файлам.
Да, в ваших словах есть истина. Я сначала предложил, а только, потом, подумал :-)
Спасибо за критику.
> предложение новой функции array_column
И ведь запихают в глобальное пространство имен, и старый код с аналогичными пользовательскими функциями работать не будет на новых версиях PHP.
Эм… if(!function_exists('array_column')){ function array_column(…){…}} не?
Вы не поняли, к чему я это сказал.
Код мог быть написан до появления 5.3 с неймспейсами.
И содержать эту функцию. Или другую функцию, или класс.
И реализация наверняка бы отличалась. Ну, к примеру, другим порядком параметров. Или вовсе делало абсолютно другое.

Т.е. я считаю, что захламлять глобальное пространство имен — плохая идея.
Учитывая существование пространств имён, если программист использует глобальное пространство — то он ССЗБ.

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

Как по мне, то это равнозначный косяк и для тех, и для других.
Ваше решение проблемы? Не добавлять новые функции? Добавлять в пространство имён PHP_internal_do_no_use? :)
Мое решение проблемы — strict режим, выключенный по умолчанию.
Выключенный по умолчанию для целей обратной совместимости.
При этом хотелось бы видеть функции для строк/массивов не просто перемещеными в неймспейс, а нормальыми полноценными методами строк. Типа " foo ".trim()
Как минимум разнести старые функции стандартной библиотеки по пространствам имён \PHP\… с соответствующим переименованием (вместо \array_merge \PHP\Array\merge), объявив старые depricated aliases. Это позволило бы к следующей (6.0?) версии избавиться от унаследованного именования вообще.
Та же мысль пришла в голову. Но лучше с PHP, чем без него, конкуренция — это всегда хорошо :)
У слона растёт змеиный хвост.
И рубиновый хобот :) Няшка :)
Или откуда-то торчит коллектив шоу Монти Пайтона? :)
Вам default и куча аргументов не нравится? Как же интересно должна выглядеть createThumbnail($source, $destination, $cropX1, $cropY1, $cropX2, $cropY2, $backgroundColor, $quality, $forceRegenerate)?

Я не пойму, кому может нравиться такое:
    public $hours {
        get { return $this->seconds / 3600; }
        set { $this->seconds = $value * 3600; }
    }

Как скажите в наследнике переопределять эти вещи? parent::set($value) что-ли? И нормально ли будет дебажить тормоза, когда $this->hour = 5, делает меняет не только $hour (да и вообще вдруг тормозит). Это же функция с побочным эффектом, но завуалированная под аттрибут.
<?php

$imagine = new Imagine\Gd\Imagine();
// or
$imagine = new Imagine\Imagick\Imagine();
// or
$imagine = new Imagine\Gmagick\Imagine();

$size    = new Imagine\Image\Box(40, 40);

$mode    = Imagine\Image\ImageInterface::THUMBNAIL_INSET;
// or
$mode    = Imagine\Image\ImageInterface::THUMBNAIL_OUTBOUND;

$imagine->open('/path/to/large_image.jpg')
    ->thumbnail($size, $mode)
    ->save('/path/to/thumbnail.png')
;


github.com/avalanche123/Imagine/
Спасибо, беру.
Предложенный вариант, как было замечено выше, очень походит на зачатки реализации свойств в C#. Но в нем есть модификатор new, который позволяет заменить родительское свойство, а к замененному обращаться через приведение типов.

Переопределять в предложенном варианте PHP, полагаю, так:

public $hours {
    get { return parent::$hours; }
    set { parent::$hours = $value; }
}
ClassName::$varName уже для переменных переменных используется.
Вы, наверное, имели в виду, для статических переменных. Да, вы правы, забыл о них. Тогда как в C#:

public $hours {
    get { return ((parent)$this)->hours; }
    set { ((parent)$this)->$hours = $value; }
}
В set, конечно, без $ (опечатался)

((parent)$this)->hours = $value;
Не все так плохо.

public $hours = {
    get { inherit; }
    set { /* Set value here ... */ }
}
Для меня пока что самое ожидаемое нововведение — это когда к объектам можно будет обращаться через точку "."
Ради субъективной читабельности что-ли, так скорее как в Scala -> будет автозаменяться на → в IDEшках, а язык будет поддерживать и то и другое. А точка уже закреплена за конкатенацией, так что не дождетесь :)
Никогда, наверное. Иначе как отличить от конкатенации?
Заменить конкатенацию. на +? :)
Для PHP это не проблема :)
В смысле ещё одно «это невозможно понять, это нужно запомнить».
Так что должно получиться «11» или 2?
Что напишут в мануле, то и будет должно. Для избежания разрыва шаблона скорее «11» как в JavaScript. Оба операнда строковые и нет никакого смысла их приводить ещё к чему-то.
То есть все, что было написано ранее перестанет работать?
В 5.5. depricated сделать где используется точка для конкатенации и плюс для сложения двух строк…
И на 5.6 никто не перейдёт.

Как на python 3.

Вам оно надо?
Я перейду, хостинги будут, пускай и не по дефолту, а из панели/по заявке.
И какого результата вы ожидаете от кода?
const b = 'bar';
class A {
    public $b = 'baz';
    function __toString() {
        return 'foo';
    }
}
echo new A().b;
Согласен, что не получится. Я лишь в теории высказался, т.к точку-конкатенацию никто не станет переделывать на "+". Javascript в этом плане удобен, но некоторые операции с "+" порой имеют непредсказуемые результат, если не знать некоторых тонкостей.
Дружище, ты в каждый пост о php будешь копипастить этого капитана? Понравилось карму поднимать?
Похоже это был последний раз. И я, в виду такого случая, даже глянул что же это за «Капитан PHP»
Отказ от поддержки Windows XP и 2003

Мне-то пофиг, конечно, но интересно, что такого есть в семёрке, чего нет в хрюшке, что требует ощутимой работы по поддержке.

Получение полного имени класса

Ещё бы они получение имени функции сделали, чтобы не было «указателей на функцию» в виде array('Foo', 'bar'), которые IDE не могут валидировать. Хочу array(Foo::class, Foo::bar) или что-нибудь вроде того.

Пропуск параметров

Этим ужасом никто пользоваться не будет. Что это за синтаксический сахар, если используется длиннющее «default»? Сделали бы именованное обращение к аргументам при вызове функции, если уж так хочется поддерживать говнокодерство с методами на 20 аргументов.

Контроль типа для скалярных значений

Наконец-то они одумались! Нужна не строгая проверка на тип, а приведение.

Getters и setters

Наконец-то! Ненавижу, когда ради обращения к свойству приходится производить кучу операций на строках — курам на смех.

Генераторы
Выделение списков и выражения-генераторы

Звучит офигительно! Хочу. Особенно учитывая, какой кошмарный код приходится писать для реализации LINQ в PHP — при использовании ленивых вычислений код становится трудно читаемым.
Этим ужасом никто пользоваться не будет… если уж так хочется поддерживать говнокодерство с методами на 20 аргументов

Ошибаетесь. И я еще жду ответа на вопрос как разговнокодить createThumbnail($source, $destination, $cropX1, $cropY1, $cropX2, $cropY2, $backgroundColor, $quality, $forceRegenerate)
> И я еще жду ответа на вопрос как разговнокодить createThumbnail

В идеально мире: создать класс Thumbnail, в конструктор передавать $source, также добавить в него методы для установки всех свойств (setCrop и т.д.) и потом вызывать create($destination).
также добавить в него методы для установки всех свойств

Фигня это, а не идеальный мир, имхо. Нафига писать 7 вызовов set* и в конце 1 create вместо того чтобы вызвать create с 8 параметрами? И, кстати, а чего для desination отдельного set не предусмотрели?
> Нафига писать 7 вызовов set* и в конце 1 create вместо того чтобы вызвать create с 8 параметрами?

Ниже ashofthedream почти тоже самое написал, но если вам непонятно в виде слов, то вот код:

$thumb = new Thumbnail($source).

$thumb->setCrop($cropX1, $cropY1, $cropX2, $cropY2);
$thumb->setBackgroundColor($backgroundColor);
$thumb->setQuality($quality);

$create = $thumb->create($destination, $forceRegenerate);

if (!$create) {
// bla bla bla
}

Непонятно где вы тут семь сеттеров насчитали. На последний вопрос думаю не нужно отвечать?
Мне сложно оценить семантику, но почему не setCropAndBackgroundColor? И что будет если не задать Crop или Quality? Имхо, сеттерами можно либо задавать необязательные параметры, либо изменять установленные конструктором 9в особых случаях рефлексией). Но если математической формуле требуется 8 параметров, то и нужно ей передать 8 параметров. В крайнейм случае сгруппировав их в объекты/массивы, то есть код должен быть типа такого:

$crop = new Crop($cropX1, $cropY1, $cropX2, $cropY2);
$thumb = new Thumbnail($source, $crop, $backgroundColor);
$create = $thumb->create($destination, $forceRegenerate);

if (!$create) {
// bla bla bla
}

Причём $crop введена лишь для удобства чтения, можно было её вставить new Crop($cropX1, $cropY1, $cropX2, $cropY2); в конструктор Thumbnail непосредственно.
> Мне сложно оценить семантику, но почему не setCropAndBackgroundColor?

Потому что мне так удобнее :) Если что-то не указано, то будут использованы параметры по умолчанию, которые в *моей* реализации имеют подходящие для моего случая значения.

> $crop = new Crop($cropX1, $cropY1, $cropX2, $cropY2);

Если Crop используется только для хранения четырех значений, то он, ИМХО, лишний и лучше просто передать их в метод.

> $thumb = new Thumbnail($source, $crop, $backgroundColor);

Это практически ничем не отличатся от такого:

$thumb->setCrop($crop);
$thumb->setBackgroundColor($backgroundColor);

Все зависит от личных предпочтений разработчика, кому то вон цепочки нравятся :)
Потому что мне так удобнее :)

Вопросов больше нет :(
> Вопросов больше нет :(

А что вы хотели услышать? Что не логично (как минимум) изменять совершенно разные по смыслу свойства через один метод? Ну, так, это вроде и так всем известно. Смысл повторяться?

С тем что «каждый в итоге пишет именно так как ему удобнее в конкретном проекте» (например, вам все сразу передать в конструкторов, мне — изменить позже через сеттеры) спорить не будете? Поэтому нет никакого смысла обсуждать обычные пять строк кода, тем более, что он полностью отвечает на изначально заданный вопрос (хотя и он сам по себе излишен — все написано в первом комментарии).
Думал, что объясните необходимость иметь возможность изменять свойства одноразового по сути объекта.
Тогда и надо было спрашивать об этом (в вашем комментарии совсем другие вопросы написаны).

Кстати, а ваш вариант разговнокодивания какой?
Просто очень разговнокодить, достаточно сделать из вызова одного метода некий билдер.
Thumbnail.from(source)
.crop(100, 100) 
.quality(3)
.forceRegenerate(true)
.blabla(somearg)
.create(destination);


Функция не обязательно должна иметь много параметров, что бы захотеть их пропустить:
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' ]] )

3 параметра, 2 из которых не обязательны — это много или мало?
htmlspecialchars(<4 параметра>) — это кривая функция?
Что htmlspecialchars, что html_entity_decode — не совсем красивые (да, тут наверное можно упомянуть слово кривые) функции, по хорошему они должны выглядеть так:
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' ]] )
html_entity_decode( string $string [, string $encoding = 'UTF-8' ] )
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401])


htmlspecialchars разбивается так же, ну вот не нужно мне указывать какие-то там флаги, зачем мне писать их, если я хочу указать кодировку? Правильно — незачем.

Но, к сожалению, дизайн языка не позволяет делать function overloading и поэтому мы имеем то, что имеем
зачем мне писать их, если я хочу указать кодировку?

Ну так не пишите:
html_entity_decode($string, , 'UTF-8'); // Отличный, удобный вариант.
// Это универсальнее, проще и понятнее чем function overloading.
Неудобно когда надо еще условие, например:
html_entity_decode($string, empty($param) ? default : $param, 'UTF-8');
В таком исключительном случае, вы можете передать дефолтное значение
html_entity_decode($string, empty($param) ? (ENT_COMPAT | ENT_HTML401) : $param, 'UTF-8');

Но:
1. такое приходится писать крайне редко. И ради 1% случаев заставлять писать себя «default» во всех остальных 99% случаев как то не гуманно. Мне в 100500 раз проще написать "" чем «default».

2. Я бы вообще не использовал тернарные условия внутри других длинных выражений. Тернарники и без того имеют сложно-читаемый синтаксис, по этому я бы разнёс на две строки:
$flags = empty($param) ? (ENT_COMPAT | ENT_HTML401) : $param;
html_entity_decode($string, $flags, 'UTF-8');


3.!!! САМЫЙ ГЛАВНЫЙ ДОВОД!!! Предложенный вами синтаксис не локаничен! Например, я не могу разбить его на 2 строки:
$flags = empty($param) ? default : $param; // что здесь обозначает default ???
html_entity_decode($string, $flags, 'UTF-8');


4. define('default', 'custom'); // Что произойдёт? Или теперь нельзя создавать константу с именем 'default'? Ох, сколько же ещё зарезирвированных слов придумают изобретатели php и как все эти слова запомнить?
По поводу (4) — скорее всего да, думаю будет зарезервированное слово, как null, true, false. И тогда конечно будет работать и (3) пункт (самый главный довод).
По поводу тернарных (2) — оффтопик, конечно лучше на другой строке, а вообще всё индивидуально.
Касательно (1) — писать default в 99% случаях — на это есть питоновский дзен — «Явное лучше, чем неявное».
По поводу (4): зачем ещё одно зарезервированное, если можно без него? Как же питоновский дзен? Представьте себе сколько появится вопросов на форумах от пхп-джуниров: «что такое default?».

Самый главный пункт №3 работать НЕ будет, потому что придётся ещё вводить новый специальный тип значений. «тип значение» != «зарезервированному слову». Иначе, представляете такой код:
$flags = empty($param) ? default : $param;
var_dump($flags); // что здесь будет?


По поводу №1. Это гораздо нагляднее:
html_entity_decode($string, , 'UTF-8');

чем это:
html_entity_decode($string, default, 'UTF-8');

В первом случае всё чётко и понятно: параметр не указан! Даже джуниоры не будут задавать вопросы на форумах — всё чётко и понятно!

Во втором случае надо ВЧИТАТЬСЯ и ОСМЫСЛИТЬ, вспомнить зарезервированное слово default, не перепутать его с null и константой defence :). Возможно у питонщиков это уже вшито в мозг с рождения, но у нас пэхапэшников пока нет.
зачем ещё одно зарезервированное, если можно без него?

Оно уже зарезервировано для использования в switch..case..default. Так что нового зарезервированного слова не появляется.

точно точно! вы правы!

есть питоновский дзен — «Явное лучше, чем неявное». 

html_entity_decode($string, , 'UTF-8');

Я пропустил параметр. Что может быть более явным обозначением пропущенного параметра?

А ещё я представляю себе две строчки в документации:
Что бы пропустить не обязательный параметр, пропустите этот параметр
// vs
Что бы пропустить не обязательный параметр, укажите специальную конструкцию языка "default"
А почему не empty?

Ну и ещё один питоновский дзен:
Особые случаи не настолько особые, чтобы нарушать правила.

это уж вопросы не ко мне, я бы тоже предпочел отсутствие параметра специальному слову — хотя бы для консистентности с list(,$val) = each($arr)
Я пропустил параметр. Что может быть более явным обозначением пропущенного параметра?

Зная любовь PHP ко всяким неявным приведениям типов я, имхо, имею полное право считать, что пропуск параметра приведётся к NULL. Никто мне не докажет, что это менее логично, чем принятие значения по умолчанию в сигнатуре функции. Вот default, да, говорит о том, что если не знаешь о чём это, то нужно заглянуть в ман.

P.S. А константы я бы вообще запретил именовать как-то кроме upper case на уровне синтаксиса.
имею полное право считать, что пропуск параметра приведётся к NULL

Не имеете:
$x = ; // это не работает.
Хотя, если «правильно» посчитать, то можно со спокойной совестью пропускать параметры используя null уже сейчас:
html_entity_decode($string, null, 'UTF-8');
null — это же ведь «ничто», т.е. я как бы «передал ничто» или «ничего не передал». В оффициальной документации вообще написано, что переменная считается null-ом если она была удалена с помощью unset(). :) Т.е. отстутвующая переменная приравнивается к null.

Я это всё к тому, что «считалка» не работает и не надо ничего считать Это же php :(

Это кстати, не единственный приведённый мной аргумент в пользу «пропуска параметра пропуском параметра». Ещё очень важна читабельность (см. 5 комментов выше).

Ну и мне ещё не охото каждый раз как мартышка печатать «default» там где можно ничего не печатать.

P.S. я бы тоже этого хотел. И ещё очень хочу что бы все уровни ошибок были включены без возможности отключения, даже NOTICE.
«передал ничто» ни в коем случае не равно «ничего не передал». Транзакция по счёту на ноль рублей не равна отсутствию транзакции (и даже баланс может измениться при транзакции). Молчание в ответ на вопрос не равно отсутствию того кому вопрос задавать…
Тогда почему вы считаете что пропущенный параметр можно приравнивать к null?
Я считаю, что пропущенный параметр это неопределенное поведение — это может быть NULL (логично с одной стороны), это может значение по умолчанию (с другой), а может быть 42 (просто так).
Хотя стоп-стоп! Сейчас можно определять константу default!!!

Я проверил на php 5.3.11:
define('default', 'custom');
var_dump('test');
Отлично отрабатывает.

Правда при попытки её использования вылетает ошибка
define('default', 'custom');
var_dump(default); // Parse error: syntax error, unexpected ...


Но дефайнить её никто не запрещал :) Возвращаю свой плюс обратно :)
Да дефайнить можно что угодно, хоть одинарную кавычку. Использовать потом, правда, неудобно, только через constant();
define("'", 123);
var_dump(constant("'")); // 123
Не всё:
define('true', false); // Notice: Constant true already defined
Кроме уже определенных констант. Это подразумевалось по умолчанию.
Гы.

var_dump(FALSE);
// bool(false)

var_dump(TRUE);
// bool(true)

define('TRUE', false);
define('FALSE', true);

var_dump(TRUE);
// bool(false)

var_dump(FALSE);
// bool(true)

Это просто жесть :)
Это вы в какой версии нашли?
в 5.3.3 и 5.3.6 такого нет. В 5.4.4, насколько помню, тоже.
А в интерактивном режиме (php -a)?
В 5.4 проверить сейчас не могу, но в остальных двух действительно так, как вы говорили. Запостите баг?
shock@shock-notebook:~$ php -v
PHP 5.3.10-1ubuntu3.2 with Suhosin-Patch (cli) (built: Jun 13 2012 17:20:55)
Copyright © 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright © 1998-2012 Zend Technologies

shock@shock-notebook:~$ php define.php
bool(false)
bool(true)
bool(true)
bool(false)
Интересно. А теперь попробуйте в интерактивном режиме.
function overloading по типу параметров для задания параметров по умолчанию — это костыль, имхо. Пропуск параметров, ключевое слово или именованные параметры выглядят куда лучше этого костыля. У них есть свои плюсы и минусы, но любой из них лучше.

Плюс, как вы предлагаете быть с функцией, у которой 3 строковых параметра, два из которых необязательные?
Создать класс CreateThumbnailParams. По вкусу можно добавить в CreateThumbnailParams конструктор, присваивающий значения полям по переданному ассоциативному массиву. Будет так:

createThumbnail($mySource, $myDestination, new CreateThumbnailParams(array('quality' => 10)))

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

Ну да, с таким конструктором обращение к полям будет через строчки, что в IDE не проверяется. Но IDE можно доработать, в теории.
Превращать опциональные аргументы в массив аргументов — это еще хуже, не формализованно. Сеттеры как у lastdragon и цепочки вызовов ashofthedream, все это еще куда ни шло. Но когда речь идет о, скажем, непубличной функции, то создавать вместо нее класс — имхо как из пушки по воробьям. Иногда функция таки зависит от 20 параметров. Есть что-то интересно в ObjectiveC стиле, вроде createThubnail($cropX1=>10, $forceRegenerate=>true), но наверное и правда неудобно рефакторить.
20 параметров для функции — это слишком много. Что она должна делать то при этом? А так, люди давно эту проблему решили, в корне, например в том же ObjectiveC. В любом языке должна быть такая вещь:
foo.do(bar: "this is the bar", really: true);

Все, читаемо, понятно, удобно, быстро, красиво.
Согласен, именованные аргументы хорошая штука
ну так никто не мешает сделать прямо сейчас в php
foo.do({ 'bar' => "this is the bar",  'really' => true });


Еще хуже: как я узнаю, не заглянув фунцкию какие аргументы она принимает, какого они должны быть типа, какие обязательные, а какие нет?
из описания функции вестимо
Опять держать открытым мануал? А если это функция напиана Васей который сидит в трех метрах от меня и правлена Петей который сидит за васей, а комменты он подправить забыл?
Зачем мануал — phpdoc достаточно и нормальный IDE работает по нему или показывает хотя бы. Вася, Петя… вы бы еще про уборщицу вспомнили, которая в теле изменила бы параметр, а в заголовке нет :)
Проблема документации в том, что она очень часто в своих проектах не соответсвует действительности. Да что говорить о документации-то, когда некоторые личности после рефакторинга тесты мьютят потому что лень править и «ну как-нибудь потом»
Конечно же я с вами согласен, но в моем случае пришлось самому покинуть такую команду.
> вы бы еще про уборщицу вспомнили, которая в теле изменила бы параметр, а в заголовке нет

А вот запросто, видел кучу кода (да и вот прямо сейчас гляжу на него) в котором в phpdoc вообще нет названий аргументов, только их типы. Поэтому phpdoc, в отличие от автокомплита, можно полноценно использовать только в идеальном мире. Да и от его *устаревания* никто не застрахован.
Если на уровне синтаксиса будет поддерживаться

foo.do($bar => "this is the bar",  $really => true );


то это будет лучше для всех, имхо. Разве что любители удалять гланды через ж… будут недовольны.
> Все, читаемо, понятно, удобно, быстро, красиво.

И куча проблем при рефакторинге.

> 20 параметров для функции — это слишком много.

А при небольшом кол-ве параметров функции эта «фича» совершенно лишняя.
эта фича совершенно не лишняя, если даже у нас 3-4 параметра для функции, один из которых не обязателен, а другие просто можем испльзовать в различных вариациях. Таких функций в пхп over 9k и часто приходиться пропускать аргументы
При 3-4 параметрах гораздо быстрее написать default (или ,,) чем вспоминать какой из них как называется (тем более в PHP).
Так для таких фич требуется поддержка IDE
Именованные параметры могут помочь и с повышением читаемости вызова при большом количестве аргументов. Например, возьмем Imagick:
$im->floodfillpaintimage($iPixel,10,$tPixel,$startX,$startY,false,Imagick::CHANNEL_DEFAULT); // versus $im->floodfillpaintimage({ $fill=>$iPixel, $fuzz=>10, $bordercolor=>$tPixel, $x=>$startX, $y=>$startY, $invert=>false, $CHANNEL=>Imagick::CHANNEL_DEFAULT });
Такой подход заметно упрощает чтение и рефакторинг в использовании метода, особенно при поддержке IDE.
Правда остается непонятно, что при этом делать в случае рефакторинга имен параметров в библиотеке, однако мне не кажется это такой большой проблемой: о том, что трудно поменять параметры местами или что-то добавить ведь никто не плачется?
Черт, никак не запомню как тут правильно код выделять, а предросмотр глючит…
$im->floodfillpaintimage($iPixel,10,$tPixel,$startX,$startY,false,Imagick::CHANNEL_DEFAULT);
// versus
$im->floodfillpaintimage({ 
   $fill=>$iPixel, 
   $fuzz=>10, 
   $bordercolor=>$tPixel, 
   $x=>$startX, 
   $y=>$startY, 
   $invert=>false, 
   $CHANNEL=>Imagick::CHANNEL_DEFAULT }); 
что при этом делать в случае рефакторинга имен параметров в библиотеке

Это по определению не будет называться рефакторингом, это уже изменение интерфейса со всеми вытекающими…
Будет. Тут нет изменений в интерфейсе (по крайней мере до тех пор пока нет именованных параметров).
Для меня это уже сейчас изменение интерфейса. Думаете замена метода Stack::popArray($countToPop) на метод Stack::popArray($countToLeave) для клиентов метода не будет означать необходимости изменения логики их обращения к методу? Синтаксически, конечно, не будет, но вот семантически скорее всего потребует, и я бы предпочёл чтобы «компилятор» мне выдал Fatal Error, а не утекла база данных несоленых паролей :)
Конкретно этот пример будет, только у вас же кроме изменения параметра, изменена и логика метода => оставить прежнее название не очень хорошее решение.

А вот если было что-то типа b($a, $b), а стало b($start, $length), то нет.
Откуда вы знаете, что она изменена? :) Именование параметров внутренне дело функции же! Захотел и изменил имя параметра без изменения логики, захотел изменил логику без изменения имени параметра. Но мне кажется, что чаще встречаются ситуации когда либо меняется и имена параметров, и логика (мой пример), либо имена функции и ей параметров (доведенный до логического конца ваш пример, например, xrange($start, $length) )
>Превращать опциональные аргументы в массив аргументов — это еще хуже, не формализованно.

что с ними не так?
Хотя бы что нужно постоянно в документацию лазить, чтобы узнать какие параметры есть. Впрочем, это отчасти решается константами класса (CreateThumbnailParams::QUALITY), но получается многословно.
Интерфейс достаточно описать в описании функции и дока в нормальном IDE будет всегда рядом
Для ключей массивов ни одна IDE не делает авкомплит. Отслеживать изменения в них гораздо сложнее (вручную). Нет проверки в рантайме со стороны языка (снова вручную и при вызове и в самой функции). и т.д.
Для ключей массивов ни одна IDE не делает авкомплит.

+100! Иной раз только из-за этого меняешь mysql_fetch_assoc на \Doctrine\ORM\EntityManager::find
ну, как вариант:
use Vendor\Image\Convert as imgconv;

imgconv\from("source.jpg")
  ->crop([10, 10, 40, 40])
  ->background(0xaabbcc)
  ->quality(80)
  ->regenerate(true)
  ->to("thumb.jpg");
// vs
createThumbnail("source.jpg", "thumb.jpg", 10, 10, 40, 40, 0xaabbcc, 80, true);
Судя по комментам, написанным во время написания моего — такой вариант весьма мейнстримен
В случае с именованными параметрами это будет выглядеть также читабельно, при этом это уже будет частью языка(то есть не нужно реализовывать функции типа crop, quality).

createThumbnail(
  $from => "source.jpg",
  $crop => [10, 10, 40, 40],
  $background => 0xaabbcc,
  $quality => 80,
  $regenerate => true,
  $to => "thumb.jpg"
);
Если с ООП, то можно наверное так:
class Crop
{
    public static $x1=0;
    public static $x2=0;
    public static $y1=0;
    public static $y2=0;
    
    public static function set($x1, $y1, $x2, $y2);
}
class ThumbPipe
{
   public static $source;
   public static $destination;

   public static function set($source, $destination);
}
class ThumbProperty
{
   public static $backround;
   public static $quality;
   public static $forceRegenerate;

   public static set($bg, $quality=80, $forceRegenerate=false);

}
$crop = Crop::set(1, 10, 52, 30);
$thumb = ThumbPipe::set('/srv/ht...', '/srv..');
$params = ThubmParams::set('#FFEE33');
createThumbnail(ThumbPipe $thumb, Crop $crop, ThumbParams $params); 


Бр… как громоздко… первое что пришло в голову… ну или второе:
$crop = array(1, 50, 20, 30);
$params = array('#FFFAAA', 85, true);
createThumbnail($source, $destination, array $crop, array $params);


Уж извините, спать хочется, возможно завтра будет стыдно за то что написал… В общем позвольте пог… кодить на ночь глядя :) Ну в общем функции с длинным списком параметров были есть и будут.
Так однозначно хуже читается. На мой вкус.
Да выше есть варианты и лучше. Но все равно в 100% не избавится от длинного списка параметров или длинной цепочки вызовов методов.
Ну в общем меня зациклило на «ну в общем», ну в общем вошел в рекурсию, ну в общем спать.
$crop = array(1, 50, 20, 30);
$params = array('#FFFAAA', 85, true);
createThumbnail($source, $destination, array $crop, array $params);

Здесь абсолютно не решается проблема вызова функции с $source, $destination и $forceRegenerate, не вызывать же createThumbnail($source, $destination, array(), array(null, null, true);

Класс же со статическими методами вообще не тру. Его ни расширить, ни замокать чтобы потестить, ни передать аргументом, ни завести два инстанса (следующий затирает предыдущий).
Я статические методы и переменные класса воспринимаю прежде всего как замаскированые глобальные…
Наконец-то они одумались! Нужна не строгая проверка на тип, а приведение.
У меня несколько иное мнение на этот счет. Можете почитать эту ветку комментов, например. А если коротко — то в современных фреймворках объект, инкапсулирующий запрос, имеет методы для получения ключей с приведеднием к заданному типу. Поэтому строгая типизация, без приведения, лучше, чем приведение «без потерь», так как разработчик всегда знает, какой тип нужно ожидать в том или ином ключе, а строгая типизация делает валидацию неизбежной.
Уже читал эту ветку, и она меня только лишний раз меня убеждает, что строгая проверка не есть хорошо. Собственно:
Итого: если вы пользовались тем, что вы описали — то для вас с появлением хинтов ничего не меняется. А если вы не пользовались этим всем — то введение хинтов на скаляры добавит головной боли.


Строгая типизация — это не PHP-way. PHP — это язык с нестрогой динамической типизацией. Не нужно выворачивать его наизнанку. Если вам хочется чего-то другого, то есть другие языки.
По мне так динамичность типизации практически не используется в нормальном коде и от добавления к ней опционально статической хуже никому не будет (ну почти, как не стило почти никому хуже от добавления областей видимости для членов класса). A PHP язык всё же со слабой типизацией, это особый вид нестрогой, но почему-то самый, вроде, популярный в вебе: PHP, JavaScript, ActionScript(не уверен).
>Ещё бы они получение имени функции сделали, чтобы не было «указателей на функцию» в виде array('Foo', 'bar'), которые IDE не могут валидировать. Хочу array(Foo::class, Foo::bar) или что-нибудь вроде того.

Тогда уж просто Foo::bar сойдет, указание на класс же есть.
Еще предлагаю убрать ключевое словов function (как минимум из декларации методов класса).
Не случится. :-( У разрабов похапэ религия: «Код должен быть читаемым, даже если ты не знаешь язык». :-/ Они фичу по сокращению записи замыканий завернули с таким результатом — это при том, что прилагался патч и всё такое.
Это неплохая вообщем-то религия :)
Для того чтобы не напрягать пальцы есть IDE, а вот с сокращениями надо быть осторожным, ведь найдется кто-нибудь кто их сразу все использует, я вот в Perl с этим столкнулся, вы как-нить посмотрите на досуге, там даже аски-картины рисовать можно :)
Было бы желание…

#include<stdint.h>//       4
#include<stdio.h>/*      76.                               1
                         ..2321     1       57             3
                         21....     .       ..             .11         1   2
                    1  88..1321  2  33    5512      1      277        14   1
                    099..12....  .  ..    ....    1 4 11111...111 122 5.1  .
                  11...221.821112411123455676489  51.176543232666 902 .27  1
                  10111...1.....................11.417...........1...21..11.
                  ..2239921176566156225563322299887...6533233233182469196894
                  22...............................111......................
*///              3269548556987776665556662131223412347543332334543322223456
/*
          13.3.37 */char C[120]  [60   ];int R[120][60],W,H,J,K,B[61][61],/*
          12.2.39 */r,i,j,c,*q  =&   H,t=7200,x,y,k;int64_t*U,T[28800],*S=/*
          11.2.40 */T,O[120],  Z[   120],v,z;void D(){for(k=-1;7200>++k;S[/*
            10.39 */k]=v)r=!         ~(v=U[k])&&*R[k/60]?2:S[k]-v?1:r;;;;}/*
             9.36 */void L(             ){for(r=1;r==1;){r=3;;for(i=0;120>/*
             9.31 */i;i++){                  for(k=z=1,j=0;v=R[i][j];j++)O/*
           8.3.32 */[i]|=(  1LL             <<v)-1<<k,k+=v,0,Z[i]=z|=1LL<</*
           7.3.30 */k++;;  v=~                (3LL<<k-2);for(j=-61;++j<60;/*
           5.3.29 */v=(   v|~                  z)&(j<0?v>>1:v<<1|1))v=S[60/*
       3.1.3.1.28 */*         i    +(j        < 0?~j:j)]|=j?v:~3;}for(z=0;/*
         1.2.4.31 ;         */    7200       >z;z++)i=z/60,j=z%60,(B[i<60?/*
           7.5.31     */i:j][   i<60?        j:i-60]=~S[z]&O[i]?~S[z]&Z[i]/*
         1.6.5.30 ;  */?r=0    :(U=O          ,1):(U=Z,2))?k=i<60?j+60:j,S/*
       5.10.12.16 */[i%    60+60*k]|=         ~U[k]:0;U=S;  S-=t*=-1;D();z/*
    5.11.5.4.12.4 */*9;  }}int main(          ){for  (;K=  scanf("%d",R [*/*
    15.2.4.4.11.5 */q+c*60]+j)<1?          q= &W,j  --,2   >++c:'\n';j =-K/*
   16.3.4.2.2.5.5 */+getchar()?j+1        :++ *q*0   );     L(   );;if (!r/*
         14.8.7.3 */)for(K=0;K<W          *60;K++)              if(K%60  </*
     12.1.4.1.6.2 */W&!B[K/60]          [ K%60 ]                  ){for(  /*
       11.3.4.6.1 */c=64;c--;         )if (!(1                     &S[K/*  ;
     10.1.8.8.5.1 */]>>c))U=        S ,000,S+=         J=14400,     D()/*  ;
         9.8.11.5 */,S[K]=~         (1LL<<c)         ,L(),S-=J,S    [K]/*
    9.5.6.1.2.4.1 */|=r==2?          1LL<<          c:0;L(  ) ;}     q=/*  ;
        9.3.5.1.5 */&K;;for           (J=          K=i=0       ;    120/*
        3.2.6.5.1 */>    i;                       Z[i]=k            --,/*  ;
        2.6.3.5.1 */                             i>59?q    =&J     :0,/*   ;
    2.1.2.6.3.6.1 */ *     q<                    k?*q=k    :0,    0,C[/*   ;
2.1.2.2.1.5.2.5.1 */ i  ++  ][                k  ]=' '     ){     j=k/*    ;
    2.1.2.5.5.6.3 */ =  0;  for(;         x=R[i  ][j++]            ;/*
      4.1.9.7.5.1 */0)  k  +=sprintf   ((00,C[    i]+/*                    ;
       5.19.6.1.2 */k), "%d.",x);}i=~J;;r&1       ||puts        (         /*
         24.6.3.3 */r?"invalid":"failed");         for(;i      <H;       i/*
     24.1.2.9.7.4 */++,puts(""))for(j=~K;j  <  W;  )putchar( i<0?j<0    ||/*
        25.1.2.25 */(k=i+Z[j+60])<0?' ':C[j +  60  ][k]:j<00?(k=j+Z[i])<0?/*
          28.1.26 */' ':C[i][k]:"?X "[B[i][j]]  ) ,j++;return 0;} /* 2012 */
что бы в место него писать возвращаемый тип, или ничего, как в любом нормальном языке. Смешно в 2012-м году такие вещи в коментариях писать
Ну тип это хорошо, но дополнительно, а не как замена.
В питоне и руби def, в джаваскрипте и пхп function. Зачем убирать? Про возвращаемый тип — согласен.
php далековат от руби и питоне и совершенно не похож на js. Убирать за тем, что он не нужен. Смысл в нем? В руби без def вообще каша будет.
Не убрать, так заменить на def или, хотя бы, func — банально короче писать.
Эмм… Как вы себе это представляете? Так, чтобы в коде не было разночтений?
Чем же вам так не угодил function, если 90% IDE после набора fu по Tab-у сам вставляют слово целиком?
Лично мне «function» не угодил разницей между

from($categories)
    ->orderBy(function ($cat) { return $cat['name']; })
    ->groupJoin(
        from($products)
            ->where(function ($prod) { return $prod["quantity"] > 0; })
            ->orderByDescending(function ($prod) { return $prod["quantity"]; })
            ->thenBy(function ($prod) { return $prod["name"]; }),
        function ($cat) { return $cat["id"]; },
        function ($prod) { return $prod["catId"]; },
        function ($cat, $prods) { return array("name" => $cat["name"], "products" => $prods); }
    );

и

from($categories)
    ->orderBy($cat ==> $cat['name'])
    ->groupJoin(
        from($products)
            ->where($prod ==> $prod["quantity"] > 0)
            ->orderByDescending($prod ==> $prod["quantity"])
            ->thenBy($prod ==> $prod["name"]),
        $cat ==> $cat["id"],
        $prod ==> $prod["catId"],
        ($cat, $prods) ==> array("name" => $cat["name"], "products" => $prods)
    );

(Выдуманный синтаксис.)

Впрочем, лично я не за то, чтобы искоренять «function», а чтобы добавить альтернативную краткую запись.
А как будет выглядеть такой упрощённый синтаксис в случае если у функции больше одного параметра?
Последняя «лямбда» — как раз пример функции с двумя параметрами. Они в скобки берутся.

Тут другой вопрос интереснее — в отличие от того же C# все используемые извне переменные нужно объявлять вручную с помощью use(). Поэтому, если стремиться покрыть и этот функционал, то надо что-то придумывать. Можно такую же абракадабру, как в C++, устроить… [var1, &var2] (arg1, arg2) {...}.
UFO just landed and posted this here
Приятно, что язык развивается. Ридонли свойства, геттеры и сеттеры, пропуск параметров, контроль скалярных аргументов — это всё очень вкусно. Интересно, что будет дальше. Именованные параметры в функциях?
Не исключено, что пропуск параметров заменится на именованные параметры, имхо.
В чем ключевое различие между использованием:
— preg_replace для замены строки и preg_replace /e для выполнения кода;
— preg_replace для замены строки и preg_replace_callback для выполнения кода?
Первое — eval, строчка. Втрое — замыкание или указатель, явный код.
А меня бы очень порадовала такая конструкция:
function some($param1, $param2, $param3)
{
  echo $param1.' '.$param2.' '.$param3;
}
$params = array(1,2,3);
some(*$params); // 1 2 3
// Сейчас вместо этого приходится писать call_user_func_array, а в случае с конструктором вообще использовать Reflection
Было бы вообще шикарно! :)
UFO just landed and posted this here
Печально.
Продолжаем дальше плодить глобальные функции :(
Я надеялся на функции привязанные к пространству имен, хотя бы.

Хотя getters и setters — это очень хорошо.
Никите Попову 17 лет (!) и он рулит развитием PHP. Парень явно далеко пойдет. Честь и хвала. Чувствую себя нубом, в хорошем смысле.

P.S. кстати, блоги указанных людей очень рекоммендую:
Nikita Popov
Anthony Ferrara
Не заметил, что перевод с блога Никиты.
PHP 5.5 больше не поддерживает Windows XP и 2003. Этим системам около десяти лет, поэтому PHP отказалось от них.
Я очень глубоко скорблю.
Мне нравиться что язык развивают и мне нравиться нововведения ( привет python! )

Но что мне не нравиться так это какая-то ползучая революция. Имхо надо как-то лучше управлять и новшествами и потерей совместимости. Повторяется история с 5.3, новшества которого просто не имеет смысл иметь в виду, пока он не стал повсеместным. Конечно тихой сапой он пролезает в шаринг хостинги и в пакеты, но пока не стал mainstream и может еще год не станет. Я даже не представляю когда будет актуальны изменения в 5.4, а уж 5.5 вообще боюсь не дождаться :)

Также для меня странно что внутри одной ветки 5.x есть какие-то потери совместимости.

Я думаю надо планировать стабильную и достаточно цельную по фичам версию, зарелизить ее через год и потом активно толкать ее хостерам и маинтейнерам. Иначе php так и будет в версии 5.2, в лучшем случае 5.3, до конца времен.

Все вокруг меня используют PHP 5.4.
Ну вы пробовали сделать публичный продукт на php?
Согласен про застой, но он ненадолго, да и касается только домашних страничек (остальные берут выделенный сервер). Symfony2, Doctrine2, другие популярные фреймворки (с неймспейсами) уже требуют 5.3, а с набором их популярности (т.е. уже) и хостеры зашевелятся.
Рассчитан на VPS как минимум, наверное?
Господи, у меня вытекли глаза от этого комментария.
Имхо, 5.3 давно уже мэйнстрим, хотя и приходится некоторых хостеров переключать на него с 4.x через тиккеты. 5.4, да, self hosting only практически сейчас. Но в целом динамика апдейтов мэйнстрима радует больше чем при переходе с 3 на 4 и с 4 на 5.

А Chrome и примкнувший к нему Firefox вообще приучили меня не обращать внимания на минорный это релиз или мажорный, номер версии просто идентификатор, собираешься перейти на новый — смотри ченжлогги если не нужны неприятные сюрпризы.
Изменения конечно радуют… но, дайте же наконец типизировать возвращаемые значения методов, ну и перезагрузку методов сразу уж бы…
Как бы Вы применяли перегрузку методов?
Если говорить про плюс, то мне бы арифметику объектов типа Money:
$total = $price1 + 2*$price2
$total->getValue();
$total->getValueWithTaxes();


А если о перегрузке метода в зависимости от типа аргумента то тоже неплохо
min($price1, $price2)
round($price)
ну например можно было бы избавится от проверки instanceof, когда в качестве аргумента метод принимает объекты разных типов.
А зачем типизировать возвращаемые значения, когда в PHP сплошь и рядом слабая типизация и как такового типа переменной не существует? В связи с этим и перегрузка методов выглядит под сомнением — при каждом вызове делать проверку типов дорого, наверное, будет. Компиляторц проще — он один раз проверил и всё, а унас интерпретатор.
А, РНР 6? Оно же тоже как-то должно выглядеть? Или же после РНР 5.5 появится РНР 7.0?
РНР 6 это юникод, но т.к. у них там все умерло в этом направлении, то развивают PHP5.
create_query(«deleted=0», «name», default, default, false); — чем это лучше такого:
create_query(«deleted=0», «name», null, null, false);
непонятно… Просто так добавить в язык еще одно ключевое слово?
UFO just landed and posted this here
yield ???
Даже не знаю как реагировать…
То ли кричать ура, то ли перебираться уже на python, где есть и разыменовывание, и генераторы, и именованные параметры и даже врапперы.

Не движется ли PHP в сторону Python?
Мне PHP очень нравился своей пробитой СИ-шностью!
если честно, я там больше джавости вижу =)
Заимствует лучшее у конкурентов. Это радует. Не радует, что тянет груз BC и никак не рискнёт хотя бы всю стандартную библиотеку объявить depricated и упорядочить её по нэймспэйсам и в параметрах порядок навести. Как раз от 5.5. этого ждал (без всяких оснований), чтобы к 6.0 избавиться от груза PHP3.
Мне совсем не понятно, зачем вводить новое ключевое слово «class» (в примере с FooBar::class). Ведь есть же уже константа __CLASS__, которая делает ровно то же самое, только доступная изнутри класса. Почему бы не сделать её доступной и снаружи: FooBar::__CLASS__.
+1, закиньте в рассылку internals обязательно
Хотелось бы, чтобы array_column(s) принимал массив колонок.
array_columns($array, ['one', 'two'])
И что тогда будет возвращать функция?
Верно, это должна быть другая функция для немного другой цели. Матрицу, в которой есть только эти столбцы. И ещё аналогичную функцию, возвращающую матрицу без «колонок», переданных в вторым аргументом.
Понятно, да, отдельная функция типа array_columnS() для этой цели могла бы быть полезна. Исключаемые столбцы можно было бы передавать в неё же третьим параметром:
array_columns($array, ['cols', 'to', 'keep'], ['cols', 'to', 'remove']);
Какой смысл исключать столбцы третьим параметром, если второй параметр и так отрежет всё, кроме перечисленных в нём? :)
Второй параметр можно было бы пропускать, например, передавая в него null. Впрочем, для удаления столбцов, пожалуй, действительно целесообразнее отдельная функция типа array_columns_remove() или array_columns_exclude(). Либо в функции array_columns() третий параметр сделать булевым переключателем: если true, то функциональность инвертируется, и указанные во втором параметре столбцы не сохраняются, а удаляются.
Да нет же…
array_columnS(array $array, array $columns, int $flag = ARRAY_COLUMNS_KEEP)
possible $flag values = [ ARRAY_COLUMNS_KEEP, ARRAY_COLUMNS_EXCLUDE]

И не надо разных функций
Нет, спасибо. Лучше уж булево true. Иначе для удобства всё равно будут использоваться функции-обёртки.
UFO just landed and posted this here
Много вещей, которые несомненно радуют.
Но какие-то все-таки эти ребята непоследовательные. C времен php 5.3 жду __getStatic() и __setStatic() вслед за __callStatic() и ничего… тихо.
Последовательность никогда не была сильной стороной PHP. Я так жду уже более десяти лет того, чтобы если где-то допустима сущность какого-то типа, то там было допустимо и любое выражение этого типа. Прежде всего это касается «операторов» (в нынешнем PHP их можно назвать таковыми только в кавычках) [],, -> и (). Чтобы конструкция типа $a[$b]($c)->$d была валидной на этапе «компиляции».
Убивает введение несовместимости с виндой. Оно конечно, если вы пишите «под» конкретного провайдера, сайт тот же, — тогда да. Но если ваш код должен делать какую-то штуку вроде системной архивации, придется использовать пхп 5.0.3, например, и «тянуть его» за скриптами.

Меня вот до сих пор преследуют private function(){} в классах, которые приводят к… дополнительному заработку когда вебмастера сами переносят сайт на новый сервер. Но лучше, бы обойтись без этого.
Зачем архивировать систему использую php?!
Вы видимо не очень внимательно читали.
Прекращается всего лишь прекращается поддержка хп и 2003.
Это не означает что на них все перестанет работать, это будет значить то, что авторы не гарантируют корректной работы.
Меня вот до сих пор преследуют private function(){} в классах

Не буду спрашивать есть ли где-то PHP4, не буду спрашивать есть ли скрипты в продакшене, работающие только под ним. Но, блин, нахрена их переносить с хоста, где они работали чуть ли не 10 лет на хост, где они почти гарантированно работать не будут?!?!?!
В пару к array_column() была бы полезна функция для преобразования списка массивов в массив, где в качестве ключа использовалось бы значение указанного столбца. Примерно так:

function array_column_to_key($input, $keyCol, $valueCol = null) {
	$output = array();

	if (null === $valueCol) {
		foreach ($input as $row) {
			$output[$row[$keyCol]] = $row;
		}
	}
	else {
		foreach ($input as $row) {
			$output[$row[$keyCol]] = $row[$valueCol];
		}
	}

	return $output;
}


На входе:
[
	[
		'id'   => 3,
		'name' => 'lorem'
	],
	[
		'id'   => 5,
		'name' => 'ipsum'
	]
]


На выходе:
[
	3 => ['name' => 'lorem'],
	5 => ['name' => 'ipsum']
]


Если указан третий параметр, то значениями результирующего массива были бы значения указанного в третьем параметре столбца:
[
	3 => 'lorem',
	5 => 'ipsum'
]
Для второго случая можно будет сделать так:
$b = array_combine(array_column($a, 'id'), array_column($a, 'name'));

Вот только будут проблемы, если ключи не обязательные и есть не у всех элементов.
Native-реализация потенциально выгодно отличается от скриптовой более высоким быстродействием. А в случае непредвиденной ситуации следует просто выбрасывать соответствующее исключение (Exception).
У нас вообще хоть одна функция выбрасывает исключения? :)
Никогда не поздно. ;-)
Возможность использовать в качестве ключа произвольный столбец теперь, начиная с PHP 5.5.0beta1, включена непосредственно в array_column() (имя столбца-ключа указывается в третьем необязательном параметре).

Возможности использования целиком «строк» в качестве значений результирующего массива посвящён баг-репорт № 64493.
Я, честно говоря, когда начал читать описание новой функции сразу подумал, что она будет делать именно то, что вы описали.

А зачем нужна она в том виде, что есть — мало понятно. Лично мне. Этот вариант, ИМХО, куда более востребованный.
Нужны обе функции. У каждой своё применение. Одна позволяет из БД-подобной структуры получить список значений (например, идентификаторов кэшируемых записей, привязываемых к кэш-записи и используемых для последующей её инвалидации), другая — получить быстрый удобный доступ к нужной записи по ключу.