Comments 251
Было бы все просто, если было бы все просто. RFC писать без предварительной реализации и без тестов не имеет особого смысла (там так и сказано). Я бы с удовольствием поддержал проект кодом. Но сколько времени займет изучение языка C и исследование внутренностей проекта, прежде чем я смогу написать что-то толковое? С учетом полной рабочей занятости, на это могут уйти годы...
обычно на это предлагают скинуться толпой и нанять сишника что бы тот запилил. И в целом предложение весьма дельное, вот только основная проблема в том что бы пропихнуть фичу дальше. И тут не надо винить мэйнтейнеров — вы там наплодите много сишного кода а им мэйнтейнить это дело еще годами. потому каждая новая штука должна быть важна.
Но давайте вспомним почему в php нет вещей в статье:
- синтаксис с "точкой" (точнее с
->
для операций над скалярами) — нет и не будет потому что заведомо проигрышная штука. Она в разы проигрывает тому же pipe оператору в плане гибкости и сложности реализации. А то что люди "привыкли" — это вопрос к тому что нужно правильно людям подать идею что бы они забросили мертвые концепты. PHP на js, там нет прототипного наследования, манкипатчинг в php никто не хочет (и правильно делает), так что нечего.
вот pipe оператор дело другое:
$result = [1, 2, 3, 4]
|> usort(($a, $b) => $a->foo <=> $b->foo)
дженерики: сложна, существует RFC и даже существуют люди которые чето пилят и обещают нам дженерики в 8-ой версии. Но есть нюансы с описанием поведения дженериков (RFC не доконца проработана и уже слишком большая) + есть целая гильдия противников подобных вещей в php. Ну и главная проблема — то что php единственный язык из тех что я знаю который делает подобные проверки в рантайме. Это глупо и в целом только по этой причине реализация тех же дженериков усложняется на порядки (потому например мы не имеем тайпхинтинга для пропертей — была реализация но сделать без сущенственного оверхэда на рантайм не вышло).
Аннотации (а точнее это больше походит на атрибуты) — основная причина по которой несколько RFC загнулись — либо расхождение во взглядах (кто-то хочет декораторы а кому-то достаточно атрибутов), расхождения в поведении (влияние на рантайм), ну и просто очень плохо проработанная RFC и плохая подача в комьюнити. Ну и так все заглохло.
короткие функции напоролись на ограничения парсера. Символ
=>
уже занят в выражениях, как и->
, варианты из Hack (==>
) никому не понравились, вариантыfn($x) => $x **2
не нравятся потому что новый кейворд + нарушение обратной совместимости (кто-то уже может юзать функциюfn
). Ну и последние варианты опять же уперлись во вкусовщину.
- Асинхронность. Вот тут в статье написан полный бред и чушь. Начиная с того что pthread тут не причем, и заканчивая тем что async/await и event loop на уровне ядра было бы круто, но не обязательно.
Было обсуждение ввести в php stackless корутины но вы можете юзать их и так через экстеншен. Да и решений для асинхронности полно.
С другой стороны среднестатистический php разработчик понятия не имеет как работает сборщик мусора и в целом весьма сильно полагается на модель "а оно потом умрет и все будет ок" что плохо совместимо со всей этой культурой. Все это делает фичи в духе асинхронности мало востребованными, ибо те кто хотят и так могут. Просто не так красиво и удобно.
Невозможно. Просто в силу того как реализован php. Ну то есть не то что бы невозможно, но сложно. Да и не очень то и нужно.
Тайпинг для переменных и пропертей — была даже реализация но как я писал выше — из-за любви к проверке типов в рантайме никто ради этой фичи не стал жертвовать 30% оверхэдом по рантайму.
наследие лет и ограничения лексера/парсера языка. Вроде как сейчас я не вижу особо проблем с тем что бы делать этот кейворд обязательным.
- Меня всегда бесило это нытье. Никто и никогда не мешал никому сделать пакет на packagist с элиасами для функций раскиданными по нэймеспейсам. И вместо того что бы решить проблему люди просто продолжают ныть.
p.s. я не то что бы говорю что php обречен, а скорее предлагаю перестать ныть и надеяться на то что php станет тем языком который нам хочется видеть.
Есть проекты вроде preprocess.io которые решают все озвученные проблемы (либо минимизируют эффект), есть анализаторы вроде psalm, есть куча крутых решений проблем, есть language server в конце концов и возможность писать свои DSL и синтаксисы с транспайлом в php и совместимостью. Но нет, всем надо просто и из коробки.
1. Перегрузка функций и методов в естественном виде.
2. Сложные ключи ассоциативных (хеш) массивов.
3. Наследование и полиморфизм, как в C++.
Отсутствие этого (или простая реализация этих пунктов) останавливает меня в использовании php.
Перегрузка функций и методов в естественном виде.
Это почти что технически невозможно. Помимо этого подобная имплементация добавит огромное количество возможных ошибок из-за механизма каста типов «на лету». Даже вариант перегружать только с разным количеством аргументов невозможен, т.к. в PHP есть вариадик аргументы, допускающие произвольное их количество.
А «почти» потому, что ваша проблема решается с помощью обычного __call, надо только придумать вам механизм диспатчеризации.
Сложные ключи ассоциативных (хеш) массивов.
Это просто структура данных. Если вам такое нужно, то реализуйте, делается минут за 5-10.
Наследование и полиморфизм, как в C++.
Это какой? Множественное наследование и возможность «дружить» классы? Это даже не смешно. Или о чём вообще речь?
2. Про сложные ключи вида (C++, из другого проекта, не CMS):
struct sOptJournalKey
{
int JournalId;
int Id;
_IP UserIp;
bool operator == (const sOptJournalKey &That) const
{
return JournalId == That.JournalId && Id == That.Id && UserIp == That.UserIp;
}
};
struct sOptJournalData
{
//…
};
CMaaUnivHash<sOptJournalKey, sOptJournalData> gOptJournals;
— не хотелось бы придумывать какую-либо склейку полей структуры ключа перед обращением $MyHash[$MyKey] = ..., возможно подойдёт ответ про SplObjectStorage из следующего ответа, php.net/manual/en/class.splobjectstorage.php, но в комментарии 37 говорится, что возможно проблемы.
3. Множественное наследование и виртуальные функции в C++ очень удобны для использования.
class PrefixedArray implements \ArrayAccess
{
private $prefix = '...';
private $data = [];
// ...
public funciton offsetSet(string $key, $value): void
{
$this->data[$this->prefix . $key] = $value;
}
}
3. Множественное наследование не нужно. Нет ни одного варианта кода где бы оно было необходимо или хоть как-то оправданно. Это в C++ просто нет трейтов/миксинов и интерфейсов. А виртуальные функции в PHP определяются кейвордом «abstract».
У меня такое ощущение, что вы не зная основ языка (имеется ввиду PHP) предлагаете туда всунуть менее удобные и надёжные, но зато привычные вам инструменты.
Хотя с перегрузкой да, печаль. Но можно вполне реализовывать её на основе рефлексии, что-то вроде:
// oneOf(callable ...$variants): self
// call(...$args): mixed
$dispatcher->oneOf('foo1', 'foo2')->call(23, 42, $arg3);
А там выбирать нужную функцию на основе сигнатуры и предопределённой логики
Перегрузка функций и методов в естественном виде.
с этим есть определенные проблемы:
function foo(string $bar, string $baz);
function foo(int $bar, int $baz);
function foo(string ...$barBaz);
foo('0', '1'); // какую из трех сигнатур должен вызвать php?
в целом перегрузка методов была бы полезной штукой, но и без этого можно вполне себе жить (просто не так удобно).
Сложные ключи ассоциативных (хеш) массивов.
http://php.net/manual/en/class.splobjectstorage.php — и дальше по аналогии. В целом обычно этого достаточно.
Наследование и полиморфизм, как в C++.
- наследование классов не очень полезная фича. В этом случае полностью абстрактные виртуальные классы как в вашем любимо C++ — это интерфейсы. И их можете спокойно множественно наследовать.
- наследование стэйта — очень простой способ выстрелить себе в ногу.
- friend классы не нужны.
- Если вы про темплейты (параметризованный полиморфизм) — дженерики появятся рано или поздно, но что-то подсказывает мне что вы не о них. Да конечно это не такая мощная вещь как темплейты но и то хорошо.
Опять же — PHP не претендует на звание хорошего языка. Увы.
1. Перегрузку в C++ использую постоянно, в том числе в конструкторах…
2. Возможно, это выход, хотя в комментарии 37 ссылка на bugs.php.net/bug.php?id=49967 (у меня не открывается сайт) о том, что могут быть проблемы. Пример хеш-таблицы на C++ в комментарии выше — CMaaUnivHash<sOptJournalKey, sOptJournalData> gOptJournals;
3. Подразумевалось множественное наследование и применение виртуальных функций, друзей стараюсь не использовать.
Шаблоны — отдельная тема.
Перегрузку в C++ использую постоянно, в том числе в конструкторах…
Я не спорю, и нахожу перегрузку методов весьма полезной фичей (хотя в целом замена оного на switch меня тоже не сильно беспокоит), просто мой пример это демонстрация вещей которые делают в php это невозможным на данный момент.
о том, что могут быть проблемы
когда-то был баг с функцией которая делала хэш от объекта, но опять же вам никто не мешает сделать свою мэпу которая как-то по особому вычисляет хэш. Это не что-то такое что часто используется в php. ну и опять же, есть php-ds который делает разруливание хэша более явно.
Подразумевалось множественное наследование и применение виртуальных функций
Множественное наследование классов прекрасно заменяется интерфейсами. А потому не вижу проблемы. Что до виртуальных функций — немного непонятно что именно вам нужно. Перегрузка методов в наследниках как бы существует. Абстрактные методы тоже.
В целом ваши притензии больше тянут на "непривычно" нежели "существенные проблемы". Что странно ибо существенных проблем у php много.
По поводу асинхронности — давно делают файберы, но пока в ядро протащить не получается (https://wiki.php.net/rfc/fiber, https://externals.io/message/101808).
А сторонних реализаций eventloop хватает.
Да и вообще, почти по всем пунктам, уже были или попытки что-то сделать по указанным направлениям, но протащить дальше rfc не удавалось.
PHP может стать еще лучшеА может не стать.
Указание типа переменным
… не обязательно делать язык со строгой типизацией
снова кто-то путает строгую (сильную) и статическую типизацию
Если уже используется laravel или lumen, то ага. А так целый illuminate/support тащить, да еще с этими фасадами — ну как то не знаю.
composer require nayjest/collection
Зато получаем поддержку километрового сообщества, актуальность и набор хелперов, которые будут использоваться 146% если знать об их существовании (например, array_first/last или class_basename).
Я согласен, что там есть и лишнее (вроде базового класса фасадов или провайдеров), но эти пяток классов — не помешают, учитывая то, что вендор любого современного фрейма и так содержит тучу неиспользуемого кода. Нет, это не призыв тянуть за собой мусор, просто меньшее зло, выбирая которое профита можно получить на несколько порядков больше.
Знаю, но не использую, чтобы не создавать привязку к фреймворку.
function class_basename($class): string
{
$class = is_object($class) ? get_class($class) : $class;
return basename(str_replace('\\', '/', $class));
}
Или я чего-то не понимаю?
Зачем весь фрейм тянуть-то?
P.S.: github.com/laravel/framework/blob/5.6/composer.json#L67
Странное, как по мне, решение формально выделить в отдельный компонент часть фреймворка, но не документировать это: laravel.com/docs/5.6/helpers#introduction — где тут о возможности подключить отдельно, без подключения фреймворка? Сравните с аналогичным решением в symfony/symfony — переходишь на страницу документации компонента и первым делом видишь `composer require symfony/`. Возможно, исключительно из-за такого подхода к документированию у Laravel есть образ сильносвязанного фреймворка, где всё друг к другу гвоздями прибито.
Вообще спасибо, открыли новое что-то о Laravel. Надо будет покопаться на досуге, глядишь окажется, что и Eloquent не часть фреймворка, а лишь компонент его экосистемы и его можно использовать отдельно, а значит не так страшно завязывать код на него.
PS Посмотрел, нет, Eloquent не отдельный компонент, судя по всему, не выделен из illuminate/database. Хотя с новым знаниями глядя на документацию можно было бы так подумать. В документации вообще логика есть? :) Можно разобрать по ней, где отдельный компонент, который можно затянуть в любой проект, а где нужно будет вручную выпиливать?
PPS В любом случае у меня культурный шок, что laravel оказывается не монолит и некоторые из фактических зависимостей от laravel/framework можно одной строчкой в composer.json выделить. Спасибо.
Посмотрел, нет, Eloquent не отдельный компонент, судя по всему, не выделен из illuminate/database.
illuminate/database и есть этот самый Eloquent и миграции.
laravel оказывается не монолит
Ну, так, относительно. По компонентам разнесено, но многие компоненты завязаны на другие, причем не интерфейсом, а прям на реализацию.
Что-то типа такого?
$result = array_map(function($x) { return $x*$x;}, explode(',', '1,2,3'));
Array
(
[0] => 1
[1] => 4
[2] => 9
)
Конструкторы и diПосле работы с magento 2 стало очевидно что нужно что-то делать с конструкторами когда внедряется di. Пример класса. Возможно, использование выражений на месте, как сказано в статье, спасет ситуацию.
Наследование классовЗнаю что проблема не php, а многих языков. Так и не пришел к хорошему решению проблемы с наследниками.
1 случай: имеется класс для выборки данных который нужно закэшировать. Можно сделать наследование и заменить все методы на кэширующие. Если класс под интерфейсом, то реализацию интерфейса. В обоих случаях придется дублировать все методы. Как это решить — не понятно.
2 случай: в magento 2 есть возможность переопределять классы (preference), но переопределить класс от которого кто-то наследуются напрямую (extends /Class) — нельзя. А класс еще может быть абстрактным. В итоге получаем кучу наследников которые нужно переопределять чтобы добавить общий метод. И простого решения нет. Трейт лишь облегчит ситуацию.
Пример класса. Возможно, использование выражений на месте, как сказано в статье, спасет ситуацию.
Я поглядел пример по Вашей ссылке и волосы на моей голове зашевелились. Я подозреваю, что такое количество аргументов конструктора может говорить о серьёзных архитектурных проблемах, а не проблемах языка.
Добавить метод через плагин? Нельзя.
Сделать замену метода где используются приватные методы? Можно, но бессмысленно (нельзя).
Плагины не отменяют проблему с наследниками. Точно так же нужно работать с каждым по-отдельности.
Мне вот недавно пришлось с головой окунуться в старый индокод, с десятками global в начале функций. В этом вашем примере класса из Magento вижу по сути то же самое, только приправленное ООП.
Не-не, как раз хорошо, что инъекции через конструктор. Были бы property injections по типу @Autowired
— было бы не так заметно, какой там ад.
В этом и заключается беда многих фремворков/цмс не использующих DI, что реальные зависимости классов скрыты
За кучу времени я и global-ы индусские переписать могу, вообще с нуля :-)
А еще при работе с системой проходят проверку на прочность все компоненты: php, mysql, phpstorm, composer. Я вот не уверен что разработчики composer планировали что обычный проект будет грузить сотни мегабайт кода. Или в jetbrains разрабатывали phpstorm только для тех у кого ssd… Куда еще увеличивать кодовую базу.
Да я это все прекрасно понимаю, у самого тонна криво спроектированного легаси, с которым приходится жить. Я это все к изначальному тезису про "надо что-то делать с конструкторами". Не надо. :-)
Запрещать подход я не предлагаю. Я за расширение: в простых случаях по-старинке, а с десятком зависимостей по-другому.
А, в этом смысле. Тут можно позаимствовать сахарок из того же Typescript:
constructor(private foo: FooInterface, private bar: BarInterface) {}
Хотя в нормальной IDE с генерацией приватных свойств и присваиванием в конструкторе проблем нет, все делается автоматически.
Docblock, который не добавляет никакой информации, а просто дублирует сигнатуру — нафиг не нужен. Если требуется правилами оформления — IDE сгенерирует сама.
В наследнике хочешь написать что-то в construct?
Ну, это вообще не очень нормально. Composition over inheritance, Abstract or final.
Вы бы хотя бы предупредили что там зрелище не для слабонервных...
Но это получается уже новый ЯП, несовместимый с PHP, но конвертируемый в/из него.
Может, как-нибудь оформлю свои заметки в статью
А что вам мешает сделать объектные обёртки для примитивов, как в JavaScript?
ArrayObject уже давно есть.
(new String("1,2,3"))->explode(",")->map(function (string $item) { return (new String($item))->intval();});
Скоро линии развития PHP и Java сойдутся в одной точке пространства-времени. Но покуда жизненный цикл PHP скрипта будет 'выполнил задачу или запрос и сдох' по-насоящему лучше он не станет.
Границ у этих, так сказать, целей нет. В этом весь фокус. Достигнув простой цели, планка требований поднимется выше, потом ещё выше, и ещё… а потом бах и OutOfMemoryException, например.
Так или иначе язык ограничен (любой язык), а задачи — нет. Так может разработчикам PHP пора начать делать что-то более серьезное чем добавление сахара из других языков? Начать с таймера и многопоточности, вот тогда язык станет языком вне конкуренции, а не темой для холиваров.
В этом и есть его крутость.
Вот представь, поднять на той же Java на одном сервере 100 сайтов, или 1000, или ещё больше. В PHP если на каждой из них нет большой нагрузки все ограничено дисковыми пространством, а Java будет стартовать каждый и держать все программу в памяти.
Есть две Java (ещё C#), есть два Python (второй Ruby), а PHP реально имеет свою нишу, в которой он незаменим.
С той же многопоточностью, конечно иногда было бы круто быстро отдать ответ и запустить процесс в фоне, но это можно с помощью очереди.
В общем, нужно понимать инструмент и использовать тот, который нужен. Другое дело, что многие используют его там, где место Java и создают сете проблемы.
В PHP если на каждой из них нет большой нагрузки все ограничено дисковыми пространствомЭто Вы про тот случай, когда основными источниками трафика на сайте являются фрилансеры и их заказчики? Так для таких целей PHP хорош как он есть, и без всяких улучшений!
Не обязательно, если есть какая-то штука, которая может развернуться на одном сервере, но нужно, чтобы каждый клиент имел свой сайт. И в администрировании PHP прост.
Большинство веба — это по сути CRUD, узелок место — это походы в бд, а те жалкие проценты, которые мог бы ускорить компилируемый язык, редко когда нужны (ну и есть модули на Си, и вершина развития этой идеи — Phalcon).
А вот из скриптовых языков PHP на голову выше всех конкурентов, кроме Groovy(но там JVM и все прелести выяснения отношений с каким-то Tomcat). А Python и Ruby рядом не стоят.
Неявное временное преобразование примитива в объект
Вы же понимаете, что это будет совершенно другой тогда ЯП? Смущает даже более формулировка "неявное временное", в Python и Ruby, скриптовых языках, к коим относится и PHP, всё представляет из себя объекты, смысл делать из PHP очередной Ruby, это противоречит его концепции? Безусловно, профит есть, но это уже полностью изменить язык, даже если учесть что это "временно"...
- Короткий синтаксис функций
RFC, указанный в статье, уже давно отклонен, вместо него есть другой, реализация стрелочных функций, что выглядит получше и довольно круто.
- Убрать function
Вот снова отсылка к JavaScript. Однако довольно странно это выглядит, в тех же упомянутых скриптовых языках, есть ключевое слово def для объявления функции, в PHP — это function. А вообще не стоит забывать, что PHP — мультипарадигмальный язык, где кроме поддержки ООП, есть и функциональная парадигма, в отличие от Java, а в JS — классы, как известно, синтаксический сахар, так что поэтому и нет лишнего ключевого слово. В общем, плохой, я бы даже назвал, рекомендацию убирать это, смотрится не очень, даже если учитывать, что это будет опциональная фишка, с целью не писать дополнительно 8 букв, находясь внутри контекста объекта...
- Навести порядок
Многое сказано правильно, но json_encode -> Json::encode
, вообще жутко, да и представить себе сложно уже, т.к. кажется, что это пользовательский класс Json со статическим методом encode, а не что-то родное от языка. Да и опять же, статические вызовы в данном случае смотрятся ужасно.
Дженерики, декораторы асинхронность — лайк, и это реально можно, если уж не реализовать (хотя всё можно, конечно), то представить себе в контексте такого языка, как PHP, однозначно.
json_encode -> Json::encode
— очень хорошая замена, т.к. в стандартных библиотеках, коей является библиотека json, все функции, свойства константы идут с префиксом от наименования библиотеки, что иногда затрудняет чтение кода (не в случае json, конечно).Зато все константы JSON_*, которые идут в этой библиотеке, можно будет вызывать не из глобального пространства, а как константы класса JSON
Вообще, как многие справедливо ругают, в PHP слишком много функций находится в глобальном пространстве. Кроме этого, данная замена позволит гибко управлять и переопределять эти функции.
В PHP функции стандартной библиотеки являются интринсиками (не уверен в корректности термина применительно к PHP, но по смыслу ближе всего) и работают с примитивными типами:
_zend_value{
zend_long lval; //int64_t
double dval;
zend_string *str; //uchar
...
}
В случае объекта — это дополнительные накладные расходы на создание и хранение этого самого объекта.
Если сравнивать варианты выполнения функции:
1.
json_encode
: найти в локальном пространстве функцию json_encode
, если в нём не найдём (что скорее всего и будет), ищем её в глобальном пространстве.2.
JSON::encode
: найти класс JSON
, затем в нём найти статический метод encode
.Мне кажется, что 2-ой способ будет выполняться быстрее. Могу ошибаться, не знаток внутренностей PHP.
- Т.к. это расширение, то мы уже имеем увеличение вермени от получения запроса до начала его обработки, так как его надо загрузить и подготовить. Ну это я чисто придраться.
- Для
JSON::encode
разрешение имен будет идти абсолютно по такому же пути — сперва будет происходить поиск классаJSON
в локальном пространстве имен, а потом в глобальном.
2. На мой взгляд, код
\JSON::encode
выглядит гораздо гармоничней, чем \json_encode
. Но это чисто моё мнение.Плюс, как я думаю, поиск в локальных/глобальных классах будет будет идти быстрее, чем в функциях, т.к. их намного меньше. Но точно этого не знаю, т.к. надо измерять.
- Вот хорошая статья про жизненный цикл PHP
- Да я, собственно, не против. PHP позиционируется как мультипарадигменный язык. Кому-то нравится ООП, кому-то процедурный стиль.
Вы вполне можете сделать свой утилитный класс с красивыми методами, проксирующими к некрасивым стандартным функциям (лично я так иногда и делаю) и даже вынести его в расширение — это не так сложно делается.
Например, встроенное расширение intl. Если зайти на страницу документации php.net/manual/ru/book.intl.php и почитать названия методов, то волосы встают дыбом — смесь CamelCase, слитное написание наименований без заглавных букв, «стандартное» наименование функций прописными буквами, разделённые нижним подчёркиванием. Плюс дублирование многих функций в процедурном стиле (функции вызываются из загруженного глобального пространства) и ООП.
В то время, как сторонние библиотеки (далеко не все, конечно) стараются держаться ООП либо вызова статических методов.
А чем в глобальном плане различаются «встроенные возможности» от сторонних библиотек?
Из этой фразы стоит убрать слово "сторонних".
В PHP есть стандартная библиотека, содержащаяся вот прямо внутри исходного кода PHP, куда входит не такое уж и большое количество функций.
Все остальное подключается с помощью библиотек расширений — это то, что лежит в каталоге ext
и включается в php.ini
(библиотеки PECL отличается от "стандартных библиотек" только тем, что они не доступны "из коробки" и подключать/компилировать их нужно самостоятельно)
Глобальная же разница в том, что для работы с функциями расширений требуется подгрузить и инициализировать соответствующую библиотеку, а функции стандартной библиотеки доступны даже если вообще ни одного расширения не загружать.
JSON — та же библиотека, только «вшитая» в ядро. Я не про неё конкретно. Есть достаточно много таких «вшитых» библиотек, некоторые из которых можно отключить при компиляции.
Так что в глобальном плане они не отличаются от сторонних. Только образование наименований функций отличается. И это порой создаёт путаницу.
Понимаю, что это из-за наследия формирования PHP, и что это не изменить. Но такая разнородность «не красит» язык.
Всё написанное прошу считать моими «мысли вслух». Это просто тезисы моего ЯП, который я создаю на основе PHP, существующий только в моей голове.
Видимо я не совсем понятно объяснил.
В PHP нет "вшитых" библиотек кроме standard
, которую нельзя отключить. И, в частности, практически все функции работы с однобайтовыми строками содержатся именно в ней.
Все, что можно отключить/подключить — является библиотеками, которые довольно условно делятся на два типа — те, которые включены в поставку (например mbstring
или json
) и те, которые PECL.
Про многопоточность в каждом еженедельном дайджесте про PHP на хабре есть отсылки.
если убрать слово `function`, то, насколько я понимаю, сильно усложнится процесс токенизации, что печально скажется на производительности. Да и не факт, что без жестко поломанной обратной совместимости не обойдется, если вдруг.
Да, сахарка со стрелочными функциями очень хотелось бы, а если это еще приправить штукой типа https://github.com/sebastiaanluca/php-pipe-operator c поддержкой из коробки, будет совсем замечательно
Ну и про порядок с array_map/array_filter etc. и со строковыми функциями конечно тоже наболело, понятно что оберток хватает, но и нативных подвижек хотелось бы
И еще, если не дженерики, то хотябы в phpdoc описание структуры массива
array[<string>, <int>], array[<int>, SomeClass[]]
Ну и про порядок с array_map/array_filter etc. и со строковыми функциями конечно тоже наболело
Малейший чих в сторону изменения поведения/порядка аргументов в функциях стандартной библиотеки PHP равносилен развязыванию маленькой ядерной войны — вроде и маленькая, но трясти и корёжить будет весь мир. Ситуация, конечно, очень печальная и, как мне кажется, решением может быть только создание параллельной стандартной библиотеки с постепенной (через 3-4 мажорных релиза) деприкацией старой.
Можно было упрятать все эти старые стандартные функции в какой-нибудь namespace и пометить как deprecated и сделать им модные современные алиасы с однотипным наименованием функции и порядком аргументов.
Кто хочет пользоваться старыми для поддержки legacy, тот подключает namespace legaсу, а остальные переходят постепенно на новые, причём этот переход можно было бы почти полностью автоматизировать средствами самого языка.
Я думал, что так и сделают с введением namespace.
Как раз не ломает же. Старые функции помечаются как deprecated, но работают.
Теперь представим, что старую стандартную библиотеку вынесли в отдельное пространство имен и добавили третий шаг в алгоритм разрешения (что само по себе костыль в ядро языка).
Тут же в проекте появится падаван, который лихо объявляет во входной точке API, в рутовом пространстве имен, что-то вроде
function strstr($a){
echo $a;
}
И всё заверте…
Пример конечно утрированный, но нарушение обратной совместимости демонстрирует.
Так не сделают. На php куча кода, который поддерживать вообще некому, просто работает и работает.
Имеет смысл добавить ООП-варианты вида $array->map(...)->reduce(...)
/ $string->length()
, а функции оставить как были для обратной совместимости.
На php куча кода, который поддерживать вообще некому, просто работает и работает.
Тогда там и версию PHP некому будет обновить, а значит ничего не сломается:)
А оно с обновлениями серверов ломается. Какой-нибудь Pentium 4 с Debian Etch не вечен. :-)
Мне вот до сих пор для старого кода приходится держать PHP 5.3, например, и только потому, что придумали сломать call_by_ref в идиотской манере. Причем, если таки сделают explicit_send_by_ref, — а это именно то, как call by ref
в этом старом коде используется — можно будет сразу ставить 7.3 (или что там будет) — все должно завестись (разве что для совсем-совсем старого кода времен php4 понадобится полифилл на ext/mysql).
array_map/array_filter
Тут порядок легко запомнить:
- у array_map varargs, чтобы скормить несколько массивов,
- array_filter можно использовать без второго аргумента, что идентично function($v) { return !!$v; }.
Вот со строковыми функциями сложнее, впрочем, IDE всегда подскажет :-)
По какой-то необъяснимой причине в статье отсутствует предложение убрать необходимость ставить значок доллара перед переменной. По той же необъяснимой причине ничего не сказано про то, что было бы лучше, если бы к полям объекта можно было обратиться не через два символа ->, а через какой-нибудь один символ.
А ведь, казалось бы, очевидные кандидаты на улучшение.
Конечно, меня это тоже бесит, но на счёт $ под точно проблема вылезет в том, что в строке "..." не понятно как искать переменную. Это то, что на поверхности, может ещё какие-то трудности.
А по -> — это переписать весь существующий код на PHP, и это не Java, где что-то скомпилировать можно и старым компилятором, тут вообще все умножится на ноль. В Плюсах с этим как-то живут.
Вообще-то я не говорил, что без этого нельзя сделать язык, я говорил, что это сломает слишком много кода.
На счёт точки в Плюсах, там она не используется для конкатенации строк.
a();
Вызов функции `a`?
Вызов метода `__invoke()` у класса, хранящегося в переменной `a`?
Вызов функции, имя которой хранится в переменной `a`?
Еще как-то?
Вызов функцииa
?
Вызов метода__invoke()
у класса, хранящегося в переменнойa
?
Вызывать то, что ближе по области видимости. Если функция a
есть в области видимости и переменная есть в области видимости — отдавать предочтение переменной или придумать другое однозначно трактуемое правило.
Вызов функции, имя которой хранится в переменной a
?
Если хочется вызвать функцию, имя которой хранится в переменной a
, можно оставить возможность поставить перед переменной a
знак доллара.
или придумать другое однозначно трактуемое правило.
Например однозначное определение переменной с использованием символа $
Вводить в язык развесистые деревья условных признаков, от которых зависит поведение кода — одно из самых деструктивных начинаний, какое только можно придумать. Особенно странно заниматься этим из-за оскорбленного эстетического чувства довольно малой части разработчиков.
или придумать другое однозначно трактуемое правило.
Например однозначное определение переменной с использованием символа $
Ну, то есть оставить, как сделано сейчас. Вам это, как я понимаю, кажется совершенно естественным и понятным. Именно то, что многим разработчикам это кажется совершенно естественным, меня и удивляет.
Описываемое вами поведение, когда у a() может означать вызов функции, а может означать вызов метода у объекта, который хранится в переменной a
, присутствует в C++ и, если программистам на C++ предложить ради упрощения разруливания этого кейса ставить значок доллара перед каждой переменной, они просто покрутят пальцем у виска.
Особенно странно заниматься этим из-за оскорбленного эстетического чувства довольно малой части разработчиков.
Эстетика тут не при чём. Набирать $ перед каждой переменной объективно неудобно и в этом объективно нет необходимости.
если программистам на C++ предложить
Зачем вы пытаетесь сравнивать ежа и ужа?
Сходите к перловикам и расскажите, что ажно три разных префикса для переменных — это неудобно.
Сходите к дельфистам и расскажите, что :=
— это трешь.
Сходите к сишникам и объявите, что от вездесущих *
и &
в глазах рябит.
Поведайте питонщикам, что выделять блоки кода отступами — это за гранью добра и зла.
Расскажите создателям Kotlin, что типы должны быть слева, потому что вы в Java так привыкли.
они просто покрутят пальцем у виска.©
Синтаксис любого языка вырабатывается с конкретными целями. У использования доллара как префикса переменной в PHP есть конкретная цель — однозначное определение переменной в коде. А нужно это для:
- Облегчения чтения кода. Вы ведь помните, что 80% времени разработчик именно читает код?
- Ускорение работы парсера. Для PHP по сути его критично время старта.
Зачем вы пытаетесь сравнивать ежа и ужа?
Я не пытаюсь делать ничего такого. Вы декларируете, что ставить доллар перед каждой переменной лучше, чем ввести правила, по которым будет определяться является a
функцией или переменной. Я в ответ пишу, что в языке программирования, в котором фича с долларом отсутствует — никто не спешит её добавлять. Почему-то вместо этой, по вашему мнению разумной альтернативы, комитет по развитию С++ предпочитает ввести правило. Мне кажется, вы попали в ловушку рационализации недостатков инструмента, которым вы пользуетесь и хочу сказать, что в языках, в которых недостатка, который вы считаете фичей, нет — никто не спешит его добавлять. Возможно именно потому, что это недостаток.
Теперь по пунктам про приведённые вами утверждения
Сходите к перловикам и расскажите, что ажно три разных префикса для переменных — это неудобно.
Неудобно, но в перле эти префиксы хотя бы нужны для раделения типов переменных.
Сходите к дельфистам и расскажите, что := — это треш.
Тему много раз обсуждали, один символ был бы лучше, но так уж сложилось исторически. К счастью оператор присваивания в коде встречается реже, чем переменные.
Сходите к сишникам и объявите, что от вездесущих * и & в глазах рябит.
Вот тут вы собственноручно приступили к сравнению ежа с ужом. У символов * и & в Си есть смысл, убрать их просто так невозможно.
Поведайте питонщикам, что выделять блоки кода отступами — это за гранью добра и зла.
Я только что объяснял, что в лишнем символе перед переменными нет необходимости. Странно будет, если я сразу после этого буду говорить, что, хотя отступов достаточно для выделения блоков кода, обязательно надо выделить блоки чем-то ещё.
Расскажите создателям Kotlin, что типы должны быть слева, потому что вы в Java так привыкли.
Опять сравнение ужа с ежом — с какой стороны объявлять тип переменной — в основном дело вкуса. Объективных аргументов за или против тут нет.
Синтаксис любого языка вырабатывается с конкретными целями.
И конкретной целью необходимости ставить знак доллара перед переменной в PHP было обеспечить возможность вставлять переменные в строки.
Облегчения чтения кода. Вы ведь помните, что 80% времени разработчик именно читает код?
В IDE можно подкрасить переменную любым интересным вам цветом. Также IDE подкрашивает переменные в зависимости от дополнительных факторов. Знак доллара облегчает чтение кода только если вы используете какой-то текстовый редактор типа Блокнот.
Ускорение работы парсера. Для PHP по сути его критично время старта.
Ну это даже не смешно. Во-первых, существенно на время старта наличие или отсутсвие значка доллара не влияет, во-вторых те, кому это по настоящему критично — компилируют код заранее.
И конкретной целью необходимости ставить знак доллара перед переменной в PHP было обеспечить возможность вставлять переменные в строки.Позвольте не поверить и попросить предоставить пруфы.
В IDE можно подкрасить переменную любым интересным вам цветом.А не в IDE нельзя. Вы удивитесь, когда узнаете, сколько разработчиков используют редакторы не обладающие развитыми возможностями подсветки синтаксиса.
Ну это даже не смешно. Во-первых, существенно на время старта наличие или отсутсвие значка доллара не влияет, во-вторых те, кому это по настоящему критично — компилируют код заранее.Во-первых — повлияет.
Во-вторых — это как раз критично для всех, кроме high load (для них тоже критично, но только на прогреве). А таковых подавляющее большинство. Тут на хабре были статьи про критичность времени отклика — почитайте.
Я в ответ пишу, что в языке программирования, в котором фича с долларом отсутствует — никто не спешит её добавлять.А в языках, где присутствует — никто не спешит убирать. Вам не кажется, что это прямо про притчу о своем уставе в чужом монастыре?
Почему-то вместо этой, по вашему мнению разумной альтернативы, комитет по развитию С++ предпочитает ввести правило.А мантейнеры PHP, почему-то, предпочитают оставить доллар. При этом они не лезут в комитет по развитию С++ с предложением все переделать как у них. Странно, правда?
Позвольте не поверить и попросить предоставить пруфы.
Ну вот, например.
Вы удивитесь, когда узнаете, сколько разработчиков используют редакторы не обладающие развитыми возможностями подсветки синтаксиса.
То есть доллар перед переменными нужен тем, кто пользуется этими редакторами? А что это за редакторы? Можно поимённо? Вы, кстати, пользуетесь ими? Или в IDE пишете?
Во-первых — повлияет.
И, конечно, у вас есть результаты тестов? Или какие-то другие пруфы? Есть?
Во-вторых — это как раз критично для всех
Значит все должны компилировать код заранее. Это ускорит старт сильнее, чем доллары перед именами переменных.
А в языках, где присутствует — никто не спешит убирать.
И в каких языках нужно перед каждой переменной ставить один и тот же символ?
Вам не кажется, что это прямо про притчу о своем уставе в чужом монастыре?
Это не притча, это пословица :). И это пословица о том, что необходимо соблюдать установленные правила, а не о том, что их нельзя обсуждать.
А мантейнеры PHP, почему-то, предпочитают оставить доллар.
Так уж здесь заведено. О том, что можно по другому, почему-то мало кто задумывается.
При этом они не лезут в комитет по развитию С++ с предложением все переделать как у них. Странно, правда?
Да и члены комитета по развитию С++ не лезут к майнтейнерам PHP с предложением всё переделать как у них. Вас это тоже удивляет?
Ну вот, например.Источник так себе, но да ладно. Вопрос на засыпку — какой процесс облегчается в результате «an ability to insert variables inside literal string values»? Не парсинг ли?
А что это за редакторы? Можно поимённо? Вы, кстати, пользуетесь ими? Или в IDE пишете?Например vi и notepad++. Постоянно пользуюсь обоими, хотя имею опенсорсную лицензию на все продукты JetBrains. (нет, notepad++ НЕ обладает развитыми возможностями подсветки синтаксиса. vi тем более)
И, конечно, у вас есть результаты тестов?А у вас? У меня есть опыт написания расширений к PHP, ковыряния в его коде и изучения принципов работы.
И в каких языках нужно перед каждой переменной ставить один и тот же символ?Perl. Перед каждой переменной конкретного типа ставится фиксированный префикс. В PHP тип один — ```zend_value```
О том, что можно по другому, почему-то мало кто задумывается.Не, ну кто бы спорил. Все вокруг дураки. Слава богу один умный нашелся и всем глаза раскрыл.
Да и члены комитета по развитию С++ не лезут к майнтейнерам PHP с предложением всё переделать как у нихТем более странно, что лезете вы и потрясаете их комитетом.
Вишенка на торте.
Как я уже писал, надо компилировать заранее, а не затачивать синтаксис под нужды компилятора.А что еще все должны делать?
Вам не кажется, что это несколько странное пожелание для интерпритируемого языка? (дабы избежать лишней итерации переписки — я пишу на Java, Kotlin, PHP, C, Objective C и чутка на ассемблере — для души)
Вопрос на засыпку — какой процесс облегчается в результате «an ability to insert variables inside literal string values»? Не парсинг ли?
Он самый. Но можно ставить доллар перед переменными только внутри строк. Везде их ставить необходимости нет.
(нет, notepad++ НЕ обладает развитыми возможностями подсветки синтаксиса. vi тем более)
Во-первых у vim возможности подсветки получше, чем у notepad++, а во-вторых подсветки и того и другого хватает, чтобы выделить всё, кроме собственно переменных. Для того, чтобы проблемы появились, надо использовать notepad.
У меня есть опыт написания расширений к PHP, ковыряния в его коде и изучения принципов работы.
А для доказательства вашего утверждения нужны результаты тестов, демонстрирующие, насколько отсутствие доллара замедляет разбор файла.
Perl. Перед каждой переменной конкретного типа ставится фиксированный префикс.
Этих префиксов несколько. Поэтому, что один и тот же символ нужно ставить перед каждой переменной, сказать нельзя.
Тем более странно, что лезете вы и потрясаете их комитетом.
Странно, что вас удивляет, что я написал, как можно улучшить PHP в статье про то, как можно улучшить PHP. Так же очень странно, что вы охарактеризовали мои слова как "потрясание комитетом", да и то, что вы вообще написали, что майнтейнеры не лезут с советами к комитету по развитию С++ очень странно. Создаётся впечатление, что вы воспринимаете выражение моей позиции как попытку покуситься на что-то сакральное.
А что еще все должны делать?
Ну пока что вы сказали, что все должны уменьшать время старта скриптов. Я с этим не спорил. Наибольший эффект достигается предварительной компиляцией.
Вам не кажется, что это несколько странное пожелание для интерпритируемого языка?
Кажется, но вы же сказали, что тут особый случай, потому что скрипт запускается и компилируется заново при каждом запросе. Значит надо компилировать.
Во-первых у vim… во-вторых подсветки и того и другого хватает...Во-первых не vim, а vi.
Во-вторых — подсветки хватает, пока парсер редактора может однозначно определить переменную. Когда он этого сделать не может, то и подсветка начинает уже не помогать, а мешать. Даже у Idea бывает крышу сносит на, вроде бы, «правильных» языках, что уж говорить о других редакторах.
А для доказательства вашего утвержденияНачнем с того, что это именно вы утверждаете, что никак не скажется. Извините, но в случае парсера ЯП доказывать отсутствие импакта должен предлагающий изменения.
Поэтому, что один и тот же символ нужно ставить перед каждой переменной, сказать нельзя.Перед каждым скаляром надо ставить $. Перед каждой хэш-таблицей надо ставить %. Перед каждым массивом надо ставить @.
Странно, что вас удивляет, что я написал, как можно улучшить PHP в статье про то, как можно улучшить PHP.Меня удивляет, что в статье про то, как можно улучшит PHP, вы предлагаете переделать его в С++. Не более того. Спасибо — не надо. Когда мне нужен С++ — я пользуюсь им, но когда мне нужен PHP, то и беру я PHP.
Кажется, но вы же сказали, что тут особый случай, потому что скрипт запускается и компилируется заново при каждом запросе. Значит надо компилировать.То, что мотоцикл имеет два колеса и может упасть на бок(пока не едет) не означает, что нужно приделать ему еще два и превратить его в машину.
Во-первых не vim, а vi.
Либо вы на своём компьютере по какой-то причине используете vi вместо vim, что удивительно, либо редактируете код на какой-то удалённой машине, что объясняет, например, ваше нежелание компилировать код. Вам в вашей ситуации, возможно, действительно имеет смысл именовать все переменные как-нибудь особенно, например начинать с доллара. Но делать это обязательным для всех нецелесообразно.
Начнем с того, что это именно вы утверждаете, что никак не скажется.
Началось всё с вашего утверждения о том, что скажется, причём скажется существенно.
Перед каждым скаляром надо ставить $. Перед каждой хэш-таблицей надо ставить %. Перед каждым массивом надо ставить @.
Да, перед разными видами переменных надо ставить разные префиксы. Поэтому утверждение, что в Perl перед всеми переменными нужно ставить один и тот же символ — ложно.
Меня удивляет, что в статье про то, как можно улучшит PHP, вы предлагаете переделать его в С++.
Это неправда, я этого не предлагал.
То, что мотоцикл имеет два колеса и может упасть на бок(пока не едет) не означает, что нужно приделать ему еще два и превратить его в машину.
Поясните, пожалуйста, что вы хотели этим сказать.
что объясняет, например, ваше нежелание компилировать код:facepalm:
Вы понимаете, что PHP — это скриптовый (интерпритируемый) язык? Что он потому и подходит для решения определенного скопа задач именно потому, что его не надо компилировать?
Началось всё с вашего утверждения о том, что скажется, причём скажется существенно.Тут было во-первых и во-вторых, но главное все же в-третьих — все равно, бремя доказательств отсутствия негативного воздействия лежит на предлагающем изменения. Изменения предлагаете вы — вам и доказывать, что они не сделают хуже.
Пока не докажете, я, основываясь на своем знании предмета буду утверждать обратное. Dixi.
Да, перед разными видами переменных надо ставить разные префиксы. Поэтому утверждение, что в Perl перед всеми переменными нужно ставить один и тот же символ — ложно.
В PHP не перед всеми переменными и не всегда надо ставить символ $. Сталобыть ваше утверждение также ложно.
Это неправда, я этого не предлагал.Именно к этому вы и ведете. Сначала вы предлагаете убрать $, аргументируя, что С++ обходятся без него. Потом начали рассказывать про компиляцию. Это все здорово, но непонятно, причем тут PHP?
Поясните, пожалуйста, что вы хотели этим сказать.Ровно то, что сказал. То, что для PHP критична производительность парсера не значит, что его надо превращать в компилируемый язык.
Вы понимаете, что PHP — это скриптовый (интерпритируемый) язык?
Понимаю.
Что он потому и подходит для решения определенного скопа задач именно потому, что его не надо компилировать?
Да, но с ваших слов веб к этим задачам не относится, потому что всем надо делать так, чтобы скрипт стартовал как можно скорее. Самый лучший способ это сделать — компилировать заранее.
В PHP не перед всеми переменными и не всегда надо ставить символ $. Сталобыть ваше утверждение также ложно.
То есть, если доллара нет, то нельзя точно сказать, что перед нами не переменная? И в каких случаях не нужно ставить доллар перед переменными?
Именно к этому вы и ведете.
Нет, не веду.
Сначала вы предлагаете убрать $, аргументируя, что С++ обходятся без него.
Мой аргумент — необходимости в долларе нет и другие языки прекрасно это демонстрируют. Вместо С++ можно взять какой-нибудь другой пример.
Потом начали рассказывать про компиляцию.
С ваших слов надо уменьшать время старта скрипта. Вот я и заговорил про компиляцию.
Это все здорово, но непонятно, причем тут PHP?
Необходимость ставить знак доллара перед каждой переменной — объективный недостаток PHP, необходимость компилировать скрипты на PHP следует из ваших слов о необходимости ускорять старт. Вот причём тут PHP.
То, что для PHP критична производительность парсера не значит, что его надо превращать в компилируемый язык.
Производительность парсера, с ваших слов, критична потому, что критично время старта скрипта, лучший способ него уменьшить — компилироваать скрипты. Если время старта действительно важно уменьшать — скрипты надо компилировать.
Это так же его объективное преимущество, упрощающее и ускоряющее трансляци. Иными словами, объективно это компромисс между субъективными «лучше».
Для того, чтобы знако доллара был объективным преимуществом php потому что он ускоряет трансляцию, время трансляции должно быть очень критично и убирание знака доллара должно эту трансляцию существенно замедлять.
С моей точки зрения, время трансляции не очень критично, потому что трансляцию можно делать заранее. Я уже несколько раз высказал это в комментариях и мне ответили, что не надо заранее компилировать интерпретируемый язык потому что это неправильно. Мне этот аргуент кажется недостаточным.
Возможно у вас есть ещё аргументы против трансляции заранее?
В целом я не считаю проблемой если парсер php вдруг начнет в два раза дольше разбирать код, если мне будут доступны более удобные синтаксические конструкции. Да и разговоры о AOT компиляции php ходят уже пару лет как.
Как никак у нормальных людей есть opcache. Что до профита "поправил и видишь результат" — опять же это актуально сегодня только при разработке (на продакшене докеры всякие), а тут время разбора не так критично (опять же opcache).
PS Почитайте, кстати, почему в Kotlin-е сделали объявления типов справа. Как-никак один из самых приятных для работы современных языков.
никогда даже и не слышали о такой штуке, как opcache
но подавляющее большинство из них смогут нагуглить гайд как ускорить их любимый друпал или вордпресс где один из первых пунктов будет "установите opcache". Так что я не вижу проблемы.
И да, я не считаю что в этом вопросе мнение большинства весомо.
почему в Kotlin-е сделали объявления типов справа
Вы так говорите, будто бы префиксная нотация это благо какое-то. Постфиксная запись сигнатур намного меньше двусмысленностей позволяет, и это очень влияет на читабельность.
Так что я не понимаю вашей отсылки.
И да, я не считаю что в этом вопросе мнение большинства весомо.
Мнение большинства совершенно не весомо, когда вы выбираете обои себе на кухню, а когда речь касается инструмента, используемого этим большинством, то извините. Может, на самом деле, это вам нужно сменить инструмент на тот, который будет вам удобнее?
Аргумент про «если надо, то нагуглят». Это как попытки любителей ручной коробки передач доказать, что АКПП отстой. Да, больше контроля, меньше расход (если быть профессионалом), но 1) порог входа сильно выше, 2) требует постоянного внимания и действий. А людям, в своем подавляющем большинстве, хочется просто крутить руль и жать педали «быстрее»/«медленнее», не отвлекаясь на постоянное дерганье какого-то странного рычага.
Вы так говорите, будто бы префиксная нотация это благо какое-то.
Какой-то вы странный вывод сделали. Я просто посоветовал вам посмотреть, почему так сделано, не более того. Собственно первопричиной этого решения называется облегчение синтаксического разбора кода.
Популярность PHP не в малой части обусловлена его простотой и толерантностью к ошибкам и новичкам (в общем случае).
и увеличение времени парсинга PHP в два раза никак на это не влияет. Не говоря о том что "в два раза" это цифра из головы, в реальности скорее всего будет меньше. Да и легко фиксится. Потому не вижу проблемы.
а когда речь касается инструмента, используемого этим большинством, то извините.
мнение можно учитывать только если оно компетентно. Иначе это не мнение даже.
Может, на самом деле, это вам нужно сменить инструмент на тот, который будет вам удобнее?
аргумент в духе "не нравится php — не пиши на нем". Он не конструктивен и бесполезен. Развивать инструменты значит не нужно?
Это как попытки любителей ручной коробки передач доказать, что АКПП отстой.
Некорректное сравнение. Начиная с того что оно не передает "если надо", заканчивая тем что никто ничего не сравнивает.
Вы сами говорите что ручная коробка чуть меньше ест, но это не повод отказываться от АКПП если вас устраивает.
Ну и тут более корректно сравнение "другой АКПП". Так как подключение opcache не требует никаких дополнительных действий. Это как переключить режим коробки.
Собственно первопричиной этого решения называется облегчение синтаксического разбора кода.
в силу меньшего количества интерпритаций выражений. Это проще и для восприятия. Если бы это было не так — они бы чуть чуть заморочались, так как у них упор именно на читабельности.
Это ведь вы с потолка взяли про "в два раза дольше парсить" и на основе этого строите весь спор.
Словом, ваша позиция мне ясна, моя видимо вам тоже. Следует закругляться.
Это ведь вы с потолка взяли про «в два раза дольше парсить» и на основе этого строите весь спор.Нет, это я цитировал вас.
мнение можно учитывать только если оно компетентно. Иначе это не мнение даже.И почему вы решили, что ваше мнение более компетентно?
аргумент в духе «не нравится php — не пиши на нем».Это не аргумент, а предположение. Если существующий инструмент вам не подходит, то вполне имеет смысл поискать более подходящий. В этом предположении нет совершенно ничего обвинительного или оскорбительного.
Если бы это было не так — они бы чуть чуть заморочались, так как у них упор именно на читабельности.Вот нет. В кулуарах прямым текстом рассказывают, что именно простота парсера сыграла решающую роль — остальное подтянулось постфактум приятным бонусом. Также это в некоторых докладах Бреслава проскакивало (на ютубе записи с названиями а-ля «введение в Kotlin»)
Словом, ваша позиция мне ясна, моя видимо вам тоже. Следует закругляться.ну ок
Трансляция заранее превращает интерпретируемый язык в компилируемый
У меня такое впечатление, что мы говорим о разных вещах. Уже упонянутый opcache разве лишает нас каких-то преимуществ скриптовых языков?
То есть доллар перед переменными нужен тем, кто пользуется этими редакторами?
Мне нужно внести какие-то небольшие изменения в код или посмотреть на строку, в которой возникает ошибка. Я подключаюсь по ssh, ввожу nano name.php или vi name.php и читаю код. А вы мне предлагаете IDE ставить. На сервер. Который бы в консоли работал. Мне почему-то сразу хочется послать в известном направлении с такими предложениями.
Операция компиляции происходит при каждом(!) выполнении скрипта. Эта задержка, какой бы малой она не была, добавится ко времени отклика вообще каждого скрипта. Это как раз тот случай, когда экономия на спичках оправдана.
Если рассматривать средней сложности приложение с десятком подгружаемых классов — умножай на количество подгружаемых файлов.
Парсер в PHP достаточно прямолинеен. Введение правил, которые добавят в него ветвления и дополнительные проходы приведет к непрогнозируемому росту сложности и, соответственно, времени выполнения.
Операция компиляции происходит при каждом(!) выполнении скрипта. Эта задержка, какой бы малой она не была, добавится ко времени отклика вообще каждого скрипта. Это как раз тот случай, когда экономия на спичках оправдана.
Как я уже писал, надо компилировать заранее, а не затачивать синтаксис под нужды компилятора.
в ubuntu, docker образах официальных и вроде как в centos нет. Там надо ставить отдельно.
если мне приходится его устанавливать то включить вообще не проблема.
Парсер в PHP достаточно прямолинеен.
это не делает его простым. Да и "ветвлений" там и сейчас не мало. Да, и уже сегодня opcache является тем самым "дополнительным проходом", который занимается устранением мертвых веток из AST, оптимизирует что может и т.д.
Или просматриваете где-то на гитхабе. Или книгу читаете.
Гитхаб раскрашивает код. В книгах он зачастую тоже раскрашенный, но, если вы читаете нецветную книгу и оттенков серого для раскраски не хватило, то может быть доллары принесут какую-то пользу. Но лично я считаю, что этого недостаточно, для того, чтобы оправдать их существование.
чтобы оправдать их существование.
скажите спасибо что в 2018-ом году вы можете назвать метод list
или for
. Доллар вам мешает.
Просто учитывайте тот факт что до 2012-ого года php разбирал код очень примитивным образом. Контекстно зависимый лексинг там появился тоже не так давно и не сказать что сильно круто сделан.
Сегодня проблема php — отсутствие возможности определить разницу между
yield $foo => $foo ** 2;
и
yield ($foo => $foo ** 2);
(собственно по этой причине нет коротких функций в php).
Сегодня проблема php — отсутствие возможности определить разницу между
А проблема в чём? Скобки определяют группу, т.е. полноценную продукцию (ну или нетерминированную ноду AST), всё внутри парсится как отдельная структура. Получается, что первый вариант — это тупо кей-валью корутина, а второе — велью от лямбды. А ты забываешь, что там (в PHP т.е.) под капотом полноценный LALR парсер, который разруливает такие штуки «на раз-два».
Мне кажется тут другая проблема. В пыхе сделали очень крутую фичу — это секцию use — явную передачу переменных в замыкание, что позволяет GC не бояться и уничтожать все остальные переменные, которые выходят за пределы скоупа (точнее у которых refcount = 0), оставляя только нужные. А в случае таких коротких лямбд — таких переменных не будет, пыху придётся захватывать весь скоуп и держать в памяти. А там и до адовых мемликов не далеко, JS уже через такое проходил. Разве нет?
под капотом полноценный LALR парсер, который разруливает такие штуки «на раз-два».
как бы и да и нет. Я не могу конкретную переписку найти по поводу ограничений, но суть цирка можно описать вот этим сообщением: https://externals.io/message/88651#88836
JS уже через такое проходил. Разве нет?
автоимпорт если и будет то только по значению.
Посмотрел только сейчас — ключевые слова выделяет какие-то красным, какие-то синим, синим же выделяет названия классов. Надо призначть, что переменные специально цветом не выделяются, но, так как выделено всё остальное — у меня проблем с поиском переменных в коде нет.
И вообще, если $ все не замечают и никого не напрягает — значит знак выбран удачно. Конечно, кому-то может и не зайти. Я все жду когда для php появятся свой babel и тогда заживем. И вы сможете не писать $)
на счёт $ под точно проблема вылезет в том, что в строке "..." не понятно как искать переменную
Как раз в строке с двойными кавычками можно оставить необходимость ставить знак доллара перед переменной. Тут понятно для чего он нужен и почему без него будет менее удобно.
А по -> — это переписать весь существующий код на PHP, и это не Java, где что-то скомпилировать можно и старым компилятором, тут вообще все умножится на ноль
Я бы предложил оставить старый код как есть, а в файлах с новым кодом добавить директиву, наподобии "use strict" в javascript. При использовании этой директивы для получения поля объекта надо было бы использовать точку, а для конкатенации какой-нибудь другой символ. Можно даже ->, лично у меня возражений нет :). Но лучше, конечно, какой-нибудь один символ.
Но всё это технические детали, сначала нужно хотя бы сойтись во мнении, что, если бы волшебным образом в PHP не надо было ставить доллары перед переменными и можно было бы использовать точку для доступа к полям объектов — это было бы хорошо. Но, как демонстрируют комментарии, такого единодушия среди программистов нет.
Вы, наверное, и переменные называете a, b и с, чтобы сэкономить?
Нет, не называю :). Когда экономия создаёт объективные проблемы — лучше не экономить. Но значок доллара перед каждой переменной смысловой нагрузки не несёт и, если его убрать, хуже не станет.
Банально проще писать код, если перед каждой переменной не надо набирать символ, без которого можно обойтись и для ввода которого нужно зажать шифт.
Лично мне (подчеркиваю эти два слова) знак доллара перед именем переменной гораздо удобнее — и с точки зрения читаемости, и с точки зрения всяких фишек типа подстановки значения переменной в строках в двойных кавычках. Не вижу ни малейшего смысла знак доллара убирать.
А вот насчет точки вместо стрелочки — оно можно, но ничего хорошего (в отличие, например, от дженериков) в язык это не принесет. А вот с конкатенацией и оператором ".=" будут проблемы. Так что пусть уж лучше будет привычная стрелочка:)
Лично мне (подчеркиваю эти два слова) знак доллара перед именем переменной гораздо удобнее — и с точки зрения читаемости
Если есть IDE, она подсветить переменные каким-нибудь цветом. Если без IDE, то знак доллара действительно приносит определённую пользу.
и с точки зрения всяких фишек типа подстановки значения переменной в строках в двойных кавычках
Эту функцию знака доллара можно оставить.
А в бейсике нужно нумеровать строки десятками. И что, какое это отношение имеет к будущему PHP?
Разве не любыми числами? По-моему, десятками было просто общепринято, типа кодстайл)
Да, Вы правы. Подойдет любое число. Десятками нумеровали, чтобы была возможность добавить ы последующем строки в программу без тотальной перенумерации:)
Десятками нумеровали для того, чтобы можно было, при необходимости, вставить строки без пересчета всех меток до конца файла.
Ещё нужно знак доллара поменять на знак евро, ну или рубля.
В общем, завязывайте со спиртным ;-)
Функции, работающие с массивами, не меняют исходный массив, за некоторым исключением. Вы считаете что методы вида $arr->map(...)
и $arr->filter(...)
должны следовать исходной семантике, или должны менять исходный массив, на котором они вызываются?
- Если первое, то значит ли что ваше API всегда нужно будет использовать вызывая методы по цепочке?..
- Если второе, то каким образом, вы считаете, пользователь вашего API сможет сохранять исходный массив, если объекты в PHP по умолчанию передаются по ссылке? Всегда использовать
clone
при присвоении массивов?..
В том числе из-за таких вопросов мы до сих пор используем array_map
, а не делаем composer install ...
и используем какую-то библиотеку, реализующую подобный функционал, даже не смотря на то, что такие библиотеки уже есть. Они просто неудобны в использовании, потому подобного функционала вы не увидите в самом языке.
Ну как они могут менять? Это же элементы функционального программирования, там вообще ничего не меняется.
Признаться честно даже если такие массивы будут иммутабельные, это нисколько не сделает PHP как язык лучше, а наоборот — сделает работу с массивами ещё сложней и запутанней, чем она уже есть.
Например, сейчас ты вызываешь функцию и получаешь результат. Плохая или хорошая функция, всё очень понятно и однозначно.
В отличии от старых функций, с таким новым API типа как у объектов нужно будет в голове держать кучу контекстов: что это и не настоящий объект, и что он не меняется, и что нужно обязательно сохранять результат в какой-то другой переменной. Стоит ли такое новое API таких новых требований — я не уверен.
Не обязательно однозначно, но предсказуемо. Достаточно запомнить как работает конкретная функция, не нужно держать в голове ещё какие-то концепты.
$b = Array::asort($a, SORT_REGULAR); // получаем новый массив
$a->asort(SORT_REGULAR); // меняем имеющийся массив
Правда даже хуже чем уродливый код будет отсутствие возможности сделать нормальные подсказки для IDE, или я чего-то не знаю о возможностях докблоков.
/** @var \Class $item */
$item->get();
/**
* @method static someClass get_by_user_id(int $id) Bla-bla
* @method static someClass get_first_by_id(int $id)
*/
abstract class a {
...
Короче вот так не работает:
/**
* @method static void method(DocBlockTestClass $newThis, int $arg1, int $arg2)
* @method void method(int $arg1, int $arg2)
*/
Ну в принципе и фиг с ним, такое двойное использование одного метода с плавающим количеством аргументов и разным контекстом все равно ересь (пока разработчики языка не объявят обратное).
можно используя немножко черной магии сделать
class ArrayObj {
public $lArray = [];
public function __construct($array) {
$this->lArray = $array;
}
public static function __callStatic($name, $arguments) {
if ($name === 'asort') {
$newArray = clone($arguments[0]);
$newArray->doAsort($arguments[1]);
return $newArray;
}
}
public function __call($name, $arguments) {
if ($name === 'asort') {
$this->doAsort($arguments[0]);
return;
}
}
private function doAsort($type = SORT_REGULAR) {
\arsort($this->lArray, $type);
}
}
$a1 = new ArrayObj(["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"]);
var_dump($a1->lArray); // ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"]
$a1->asort(SORT_REGULAR);
var_dump($a1->lArray); // ["a" => "orange", "b" => "banana", "c" => "apple", "d" => "lemon"]
$a2 = new ArrayObj(["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"]);
$a3 = ArrayObj::asort($a2, SORT_REGULAR);
var_dump($a2->lArray); // ["d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple"]
var_dump($a3->lArray); // ["a" => "orange", "b" => "banana", "c" => "apple", "d" => "lemon"]
Fatal error: Cannot redeclare Test::method()
Язык может быть востребован по нескольким причинам: он предлагает уникальное решение для некой задачи, или же имеет большую кодовую базу. Изначально PHP опирался на первый пункт и был самым простым языком для написания веб-страниц, но тогда веб был совсем другим: никто не заботился о безопасности и поддерживаемости, важнее всего была возможность что-то слепить по-быстрому. Именно поэтому в языке изначально были такие секьюрити-дыры, как register_globals и magic_quotes_gpc. Теперь же удобных для бэкенда языков не меньше дюжины, но у PHP остается преимущество в виде огромного числа написанных на нем приложений и специалистов разного уровня.
Автор многократно упоминает в статье, что «любит PHP», но если «навести порядок» и «перенести функции в классы», в результате это будет уже не PHP, а какой-то новый язык, лишенный основного преимущества в виде кодовой базы и не дающий никаких преимуществ для привлечения новых пользователей по сравнению с конкуретами.
В отличие от фронтенда, где исторически существует только JS, на бэкенде есть огромный выбор. Почти всем пожеланиям автора отвечают, например, уже существующие Typescript/C#/Java 8. Не стоит зацикливаться на одном инструменте, когда требуемую задачу лучше решает другой.
Можно старые функции оставить, пометить как deprecated, а новое по-человечески запихивать в namespace'ы, а не в глобальную область видимости
private static function parseMethodName($token): string {
return trim(strrchr(rtrim($token, "\n\r\t */"), ' '));
}
Превратится в такое, например :)
private static function parseMethodName($token): string {
return standard\string\trim(standard\string\strrchr(standard\string\rtrim($token, "\n\r\t */"), ' '));
}
Любые функции можно импортировать через use, как и классы. Поэтому, это опять же не проблема.
если так — то может стоит задуматься почему у вас такое разнообразие зависимостей используется? Ну и всегда можно сделать так:
use function \{strlen, strpos, array_map, array_reduce};
mod_php для apache и(или) php_fpm для fastcgi
Чем эта модель исполнения принципиально лучше других? Как я понимаю, вы считаете преимуществом то, что под каждый запрос стартует отдельный процесс, который убивается после его обработки?
Знаете про принцип fail fast? Если в двух словах, то он звучит так: надежное приложение при ошибке падает и ничего не делает. PHP же всегда старается сделать хоть что-то, зачастую неправильно и, что еще хуже, молча — так вы можете потерять данные и даже не заметить этого. Там даже есть специальный оператор управления ошибками, который «затыкает» ошибки, возникающие во время вычисления выражения!
Буквально вчера у меня был случай, когда используемый уже много лет скрипт на PHP молча потёр мои данные. Скрипт выглядел примерно вот так:
$data = json_decode(file_get_contents($cache), true);
update($data);
file_put_contents($cache, json_encode($info, JSON_PRETTY_PRINT));
Оказалось, что скрипт был запущен в PHP 5.3, а флаг
JSON_PRETTY_PRINT
появился только в PHP 5.4. В результате json_encode
молча вернул NULL
, и даже в json_last_error
ничего не было, а данные пропали.пенять на язык тут не нужноНичего подобного. Была проверка на ошибку, но в данной ситуации не было ни ошибки, ни результата. Такую ситуацию я не предусмотрел, и моя претензия именно к принципиальной возможности ее возникновения.
Скрипт был изначально невалиден как минимум по двум причинам. Во-первых, идентификатор
JSON_PRETTY_PRINT
не был объявлен, что даже в весьма либеральном JS считается ReferenceError
, но PHP предпочел молча превратить его в строку. Во-вторых, json_encode
на вход был передан аргумент неправильного типа, а он молча вернул NULL
. В документации, кстати, сказано, что в случае ошибки возвращается false
. В обоих случаях не было даже notice!Люди ошибаются. Поэтому строители носят каски, а альпинисты используют страховку. И только бесстрашные программисты продолжают писать на языках с неявными эффектами :)
error_reporting(E_ALL)
полная тишина. Правда, я использую IIS — возможно, дело в этом.А error_log вообще включен? :)
Вообще, стандартная практика, используемая во всех современных фреймворках — на каждую ошибку, включая notice, выбрасывать исключение. Да и без фреймворков тоже стандартная, делается в 5 строк кода.
Python:
a = b // NameError: name 'b' is not defined
Javascript:
a = b; // ReferenceError: b is not defined
Ruby:
a = B // uninitialized constant B
"Внутренняя несогласованность в PHP вызвана тем, что язык долгое время развивался людьми, который не имели четкого представления о дизайне языка, а зачастую вообще не понимали, что они делают."
Хорошо, что в отличии от авторов JS они хоть наркоту не употребляли ))))
Смешение парадигм тоже может быть вполне оправдано — например, элементы функционального программирования в императивных языках сейчас прижились повсеместно. Нужно смотреть на конкретные реализации.
Как по мне, PHP неплохо развивается как ОО язык, и большинство функций, констант и п.р. можно переместить в классы (json_encode -> Json::encode, cUrl).
Можно по-быстрому набросать преобразование вызова статического метода в вызов стандартной функции, вроде этого:
github.com/uavn/artwrap/blob/master/Art/Wrapper/Hash.php
Странная эта мания превращать один инструмент в другой, потому что привыкли или потому что удобная фишечка. Комбинируйте инструменты а не затачивайте молоток что-бы получить отвертку.
«В PHP может быть множество задач, которые хотелось бы сделать асинхронно, не дожидаясь окончания выполнения. На ум сразу же приходят работа с большими БД запросами и HTTP запросами. Чтобы составить большой отчет, приходится либо долго ждать, либо пользоваться сторонними решениями, типа очередей. В моем случае, в проекте в большом количестве используются Slack уведомления и Mailgun оповещения. За один клиентский запрос может быть отправлено около десятка HTTP запросов. Почему бы не запустить это все на фоне, а клиенту уже отдать страничку? » потому что «Этот язык был создан для конкретной цели и решает он свою задачу хорошо. Схема „принял — обработал — отдал — умер“ очень эффективна и решает проблему небольших утечек памяти.». Не только кстати утечек памяти.
- Доступ к элементам объектов через
->
, которое ну очень часто получается как_>
ну или-.
(рукопопы как я, которые имеют рассинхрон между руками, поймут). Вот что угодно лучше служебного оператора из двух символов, один из которых по шифту вводится.. - Инициализация значений именованного массива через
=>
(ну какого черта не:
?) - Ну и как уже сказал автор — нельзя использовать выражения везде. Да даже если бы можно было хотя бы в строках делать было бы уже хорошо:
вместо$a = "Hello ${$b?:'hell'}";
$a = "Hello " . ($b?:'hell') . "!";
По третьему пункту.
$a='a';
$b='b';
echo "Hi $a! I`m $b";
Раскладывается на такие токены
1: T_OPEN_TAG = <?php
2: T_VARIABLE = $a
2: =
2: T_CONSTANT_ENCAPSED_STRING = "a"
2: ;
2: T_WHITESPACE =
3: T_VARIABLE = $b
3: =
3: T_CONSTANT_ENCAPSED_STRING = "b"
3: ;
3: T_WHITESPACE =
4: T_ECHO = echo
4: T_WHITESPACE =
4: "
4: T_ENCAPSED_AND_WHITESPACE = Hi
4: T_VARIABLE = $a
4: T_ENCAPSED_AND_WHITESPACE = ! I`m
4: T_VARIABLE = $b
4: T_ENCAPSED_AND_WHITESPACE = .
4: "
4: ;
Обратите внимание, что строка в echo
по сути разбита на элементарные составляющие из констант и переменных, для которых, в последствии, произойдет последовательная конкатенация.
opcode op1 op2 result
ZEND_ASSIGN $a 'a' x4
ZEND_ASSIGN $b 'b' x4
ZEND_ROPE_INIT 'Hi ' $_tmp_4294967290
ZEND_ROPE_ADD $_tmp_4294967290 $a $_tmp_4294967290
ZEND_ROPE_ADD $_tmp_4294967290 '!I'm ' $_tmp_4294967290
ZEND_ROPE_END $_tmp_4294967290 $b $_tmp_4294967290
ZEND_ECHO $_tmp_4294967290
ZEND_RETURN 1
В случае подстановки в строку выражения, как минимум, потребуется:
- Определение конца выражения — просто взять следующую закрывающуюся фигурную скобку не получится.
- Сделать по выделенному куску дополнительный проход токенизатором, так как по сути это инъекция куска кода.
- Как-то на этапе компиляции разрулить ситуацию, что перед
ZEND_ROPE_*
необходимо это выражение вычислить. - Не забыть, что вы можете встроить несколько выражений, да еще и с побочными эффектами.
- наверное что-то еще.
Впрочем, как из MySQL 3.x вырос MySQL 8.x, так и из PHP постепенно вырастет…
Но — я бы язык тогда переименовал, а то выражение «умеешь ли писать на PHP» с годами будет означать очередную, новую итерацию языка, во многом отличную от старых — это создаст путаницу. А если подумать (а как без этого?) о совместимости со старым кодом, которого, все же, вагон и маленькая тележка (скажем прямо — из-за него про PHP и помнят), то нужен либо режим совместимости (в php.ini писать «mode=5.5», не к обеду будет PHP5.5 помянут), либо, и правда, язык назвать чем-то вроде NewPHP.
кроме факапа с 6 версией
Ну вы же сами себе и противоречите. Впрочем, раз в 3 мажорные версии можно и потерпеть пару лет, как скажете. Шутка, лично мне это неприятно.
Другое дело, что в "новом", расширенном языке что делать — тянуть различия с третьей ветки (я про совместимость), или так и жить в режиме "у вас какая версия того, что вы называете PHP?" Минимум сбивает.
Хочу сказать только то, что из PHP не обязательно делать язык со строгой типизацией. Достаточно только дать такую возможность.
А это не оно?
declare(strict_types=1);
Не знаю точно версию языка, где это появилось, но точно после 7.0
Если код написан не портянкой, то это значение очень скоро улетит в аргумент какой-нибудь функции, так что проблема надумана.
По 1-му пункту: https://github.com/crocodile2u/chainy
PHP может стать еще лучше