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

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

НЛО прилетело и опубликовало эту надпись здесь
Я вас таки умоляю. Расскажите это создателям C# — который в принципе состоит из таких вещей, чуть менее, чем полностью. И ничего, все счастливы и требуют еще больше сахара!

PS: Нужно признать что там весь сахар органично накладывается на базу языка, а не как в случае с пхп8, но сам факт…

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

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

Так что это не имеет значения. Порог входа в шарп останется тем же самым, что и 17 лет назад. А если какому-то джуниору придет в голову запихать ArrayList на прод, то ему очень быстро и доходчиво разьяснят, что время таких вещей безвозвратно ушло.
НЛО прилетело и опубликовало эту надпись здесь
Ничто не идеально в нашем мире. Тут вы безусловно правы.

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

Но это приходит потом. Совсем потом.

Я студент который пропускал пары по шарпам. Почему не хорошо запихать ArrayList на прод?

Если коротко, лучше юзать к примеру List, т.к. он типизированный, в отличии от ArrayList который воспринимает все как object, что влечет к лишним упаковкам и распаковкам (unboxing)
Можно писать и на с++ как на «с с классами», только вот ты ведь не один работаешь на проекте — другие будут использовать все фичи, в которых тебе придется разбираться так или иначе
никто не запрещает пилить код на шарпе 10-летней давности

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

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

НЛО прилетело и опубликовало эту надпись здесь

А что там такого невыучиваемого добавилось? Каждый релиз это пяток фич которые прочитваются в блогпосту на 15 минут.

Прочитать про действительно новую фичу, которую не видел до этого — не то же самое, что и выучить её. Неиспользуемое на практике — забывается…

Там все фичи уровня "один раз прочитал — и умеешь пользоваться". НУ что там — readonly структуры? Оператор ?.? То что разрешили инициализировать проперти без сеттеров? То что разрешили для однострочных функция не писать return?


А все версии сишарпа начиная с пятой выглядят именно так. И в следующей версии судя по результатам митингов опять добавят мелочь типа "можно не писать скобочки у неймсейса" или "Relax rules for trailing whitespaces in format specifier".

В предыдущей версии появилось nullability, а в следующей record types

НЛО прилетело и опубликовало эту надпись здесь

Ну да, можно писать класс с круглыми скобочками class Person(string Name, string Password), и он нагенерирует рекорд с Equals/GetHashCode и прочей ерундой. Я полгода назад почитал про этот пропозал, вот сейчас я вам рассказываю, что это такое. Один раз прочитал — могу пользоваться ¯\_(ツ)_/¯

Если лет 10 назад C# был сравнительно лаконичным и согласованным языком, то сейчас новчику придется столкнуться с тоннами «магии» которая которая есть простопотомучто.

Потому что надо не языки учить а базовые концепции. Вон как автор статьи жалуется на связывание переменных, которое что-то "ломает".

Ну основная проблема как я вижу в нерасширяемости и ограниченности сахара, а также фрагментация. Вот сделали оператор ?. — окей, но что делать с вызовом статического метода? x?.Foo() написать можно а Foo(x?) или что-то такое уже не сделать. Соответственно код фрагментируется на тот или иной, и минорный рефакторинг привносит серьезные изменения, даже если дописать this в метод, сделав из обычного хелпера метод-расширения, и уже везде ИДЕ будет ругаться "а вот можно упростить", и наоборот.


Во-вторых расширяемость. От синтаксиса нельзя абстрагироваться. И это вообще не удобно.


Наконец, многий сахар просто костыльный. Например, завезли нуллябельные типы, вроде все рады? Но код вида T? Foo<T>() написать просто невозможно. Почему? Потому что T? для реф и вэлью типов означает совершенно разные вещи.

Вот тут вы не правы. Hемного странно в посте о пхп рассуждать о шарпе — но что имеем, то имеем.

Шарп базируется на 3 абстракциях — это делегаты, перечисления и синтаксические деревья (привет LINQ).

Указанный вами оператор?.. — это всего лишь частный случай вызова делегата. Он не может вызываться как то вне семантики делегатов — т.е. Foo(x?) — будет невалидным с точки зрения именно базового устройства языка. Причем Foo(x)?.(z) — вполне себе идиоматичная конструкция (хоть и не используемая).

Весь сахар он четко накладывается именно на каркас языка, на то что в него вложили почти 20 лет назад. Да, кажется — что некоторые конструкции уходят прямо в какие то сверхвысокоуровневые дебри, но это только кажется.

За «нуллябельные» типы, в целом согласен, их очень сильно сбоку впилили, но то требование времени и хоть какая то попытка решения проблемы NullReferenceException, не самая идеальная, но ребята стараются. Лучше так, чем никак совсем.

Оператор x?.y к делегатам отношения не имеет, это просто сахар для x is null ? null : x.y. Где тут какие делегаты?


Foo(x?) — будет невалидным с точки зрения именно базового устройства языка.

Но с точки зрения того же рефлекшна инстансные методы эквивалентны статическим с дополнительным this-аргументом. И правильно делает, кстати.

Так это не проблема ?, это проблема реф-типов и велью-типов в генериках. Ей уже нцать лет.

?.. в генерик реф-типах появился в последней версии сишарпа, привет. Да и сам ?. не особый долгожитель в языке.

Тaк я и говорю, что описанная тобой проблема, по сути, никак не связана с?.. Поведение? — это просто симптом. А проблема, которая его вызывает, существовала задолго до.

Могли просто сделать опшн и задеприкейтить нуллябл, как сделала скала. Они же смогли на Span API как-то переползти, могли бы и опционалньые значения нормальные сделать.


Но им слишком дорого это делать, а их ЦА это монстры с 20-летним легаси которым неинтересны эти игрушки, им херак-херак и в продакшн интереснее, обмазавшись динамиками и рефлекшном вкупе с COM. Что весьма грустно, в середине-конце нулевых язык выглядил революционно, а сейчас просто беттер жаба для дотнета, причем не факт что в самом деле беттер.

Так а в чём проблема? Используй скалу для новых проектов, для старых оставь шарп.
C# еще только обрастает сахарком, гляньте, например, на Visual FoxPro, за долгие годы развития он оброс этим самым сахарком (ну по крайней мере когда-то это казалось сахарком), что в 9 версии было уже не видно, где сахар, а где сам язык. Впрочем, функции он свои выполнял, вахту отстоял и ушел на покой.
НЛО прилетело и опубликовало эту надпись здесь
Писатели кода может и счастливы, а вот читатели — не очень, как мне кажется. Сделать одно и то же несколькими способами — это не всегда преимущество.
НЛО прилетело и опубликовало эту надпись здесь
К сожалению

Я не понимаю порой, как можно тащить в язык дженерики, и думать о них, когда в языке нет нормального Set (множества), который сделан на Map. Как по мне, это тоже пример непоследовательного подхода и попытки угодить страждущим.
И вот ниже resetme подсказывает, что в таком виде, не стоят дженерики того. Лично я скорее согласен. Они нужны, но в таком виде, субъективно, нет.

Эм, а разве в go нет дженериков?

Ну вот свеженькое обсуждение — меньше месяца назад.

Впрочем 10 лет назад когда Go только появился про них уже говорилось: Generics may well be added at some point. We don't feel an urgency for them, although we understand some programmers do.

Так что нельзя сказать, что это прям вот неожиданно возникшая фича.
Они там изначально есть в виде контейнеров, просто вы свои не сможете объявить.
НЛО прилетело и опубликовало эту надпись здесь
Издержки местной системы кармы. Расслабьтесь и получайте удовольствие.
Нет, не любой. Особенность PHP в том, что нет человека, который бы направлял его развитие.

Автор языка, Расмус не накладывает вето на подобные «улучшайзинги». Он устранился от руководства. Решения, каким будет PHP, принимаются в духе демократии, голосованием нескольких десятков наиболее активных персон…

Итог закономерен — под руководством толпы язык сползает в мейнстрим.

В мейнстриме сейчас нечитаемый яваскрипт. Поэтому и PHP всё больше становится похожим на яваскрипт и нечитаемым.
JS и pyton. Так все и есть и это плохо.
JS стрельнул не потому что чудо как хорош, а потому что оказался безальтернативен для браузерной динамики. При этом у него обфусцированный код не всегда от обычного отличишь. А pyton просто потому что многим захотелось сахарного и скриптового не в вебе ипоэтому теперь он жутко модный.
Можно начинать думать на чем будет писаться веб через 10 лет. Помянутую пару не предлагать.

Дуглас Крокфорд, который придумал JSON и JSLint, говорил, что JavaScript, в общем-то, неплохой язык, если использовать только часть тех возможностей, которые он предлагает. Похоже, 8-я версия лоббируется создателями PHPLint.


Но вообще, те перспективы, что вы описали, навевают грусть.

Видимо, по этому меня потянуло в сторону С.
НЛО прилетело и опубликовало эту надпись здесь
C99, а там как пойдет. Главное же начать.

Но уже имею некоторые плоды. Был удивлен тому что:
if (1) {
    char[] variable = "value";
}

printf("%s", variable);

этот код не скомпилируется. После PHP это была очень сочная оплевуха черенком грабель :)

А я удивляюсь этому в php, когда так пишут программисты с опытом от 3х лет. Ошибки? Какие ошибки? Заглушил на уровне error_reporting и типа норм.

Ну не, если «фонит» — значит надо чинить. Уже наловился таки сюрпризов при смене окружения во время переезда с непонятных серверов, на что-то более подконтрольное.

И вот на этом фоне автор статьи «тужит», что у него стрелочные функции куда-то что-то там «проливают». А почему тому факту, что переменная «вылилась» из if у него нареканий не вызывает? Потому что «так всегда было»?

В C++ можно даже так написать:
  if (auto handle = getHandle(...); handle != INVALID_HANDLE) {
  }
Специально, чтобы этот самый handle нельзя было после if использовать.

При этом в том же C++ — куча мест, которые сделаны нелогично. Да и в самом PHP… известная же статья. Многое, кстати, из там описанного, починили — но говорить «вот, в PHP всё было просто и логично, а теперь, вдруг, стало ужасно»… как минимум странно.

Но да — проблема того, что «синтаксический сахар» помогает программы писать, но мешает их «читать» — существует.

Вот не согласен с насчёт помогает писать, но мешает читать. Некоторые вещи пишутся на автомате, плюс генераторы и сниппеты в IDE, но потом сам не можешь прочитать, например, цепочку isset и тернарников

Скажем так: код становится проще читать посвящённым, но сложнее — непосвящённым.

Пример из C++. Такой вот код на C++14:
template<int... values>
constexpr int sum = 0;

template<>
constexpr int sum<> = 0;

template<int value, int... values>
constexpr int sum<value, values...> = value + sum<values...>;
Превращается на C++17 вот в это:
template<int... values>
constexpr int sum = (values + ...);


Проще стало понять? Понятнее? Да. Вот только при переписывании возникла ошибка. Нужно было, оказывается, писать так:
template<int... values>
constexpr int sum = (values + ...);


И на эти грабли чуть не каждый лично, рано или поздно, наступает, пока не поймёт — почему.

P.S. А isset и тернарники вроде в PHP, как и в многих других языках, были с прошлого века. И их, в общем, вполне хватало, чтобы создать нечитабельный код без всяких нововведений…
Скажем так: код становится проще читать посвящённым, но сложнее — непосвящённым.

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


И их, в общем, вполне хватало, чтобы создать нечитабельный код без всяких нововведений…

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

Эм, и чем тут отличается первый кусок кода для C++17 от второго?

Судя по ссылкам — во втором случае должно быть такое, просто khim неудачно скопировал:
template<int... values>
constexpr int sum = (values + ... + 0);
Нечаянный эксперимент показал, что вдумчиво читают немногие, а ссылки открывают — ещё меньшее число. И да, извиняюсь, DaemonGloom прав: там нужно не забыть "… + 0" приписать… иначе для нуля элементов компилятор не сможет понять «какой именно нуль» вам нужен (хотя, казалось бы, я же написал int...… но нет — этого недостаточно).

Тот же самый нечаянный эксперимент показал, что вдумчиво пишут немногие, а перечитывают перед отправкой то, что написали, вообще единицы :)

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

Я мог бы оправдываться, что-то объяснять и так далее… но… зачем?

Проще общаться там, где подобные вещи не являются нормой. Что мне, пожалуй, и стоит сделать. Спасибо за то, что раскрыли глаза.

Гм… Вот значит, как. То есть, по сути справедливое замечание на явно ошибочную ситуацию в коде — это уже «набигают». А ответ на явно язвительный комментарий в той же самой, заметьте, манере (хотя даже там на конце смайлик стоит, что значит — не стоит его воспринимать слишком серьёзно) это — «смешивают с грязью». Только почему-то у khim’а не возникало ощущения, что с грязью мешает он, когда писал свой комментарий (к вопросу о вдумчивом написании, кстати). Да и не нужен был этот комментарий уже — как khim сам отметил, DaemonGloom уже расставил точки над i. Так что же это, двойные стандарты?


Но отвечать не обязательно, вы правы, потому что… зачем?

Да, в Си пока что такого идиотизма инноваций нет. Но и там понемногу внедряют синтаксический сахар вида массивов переменной длины, а также хотят ввести ООП.
Все эти RFC не ломают старый api, можете писать код как и писали до этого если вам не нравится новые возможности. Лично я согласен что некоторые RFC например про «Публично-приватное свойство» выглядит ужасно.

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

Далеко не всегда удается попадать в проекты, которые начинают свой жизненный цикл. Бывают ситуации где:
— PSR??? мы тут три года уже пишем, но о таком еще не слышали
— пожалуйста не пиши так
$someobj->$methodName
, потому что джуниоры этой магии не поймут
— где 100+ методов, публичных, в классе контроллера это нужно поддерживать
— где тебя просят сделать элементарные вещи, а получается, что надо сначала там всё отрефакторить, чтобы сделать элементарную вещь. Иначе это будет просто очередной мазок сами знаете чего. Или то что было сделано хорошо, просто утонет в том что было сделано так как умели прошлые коллеги.

Это те «сливки», с которыми я столкнулся за прошедший, не календарный, год, во время поиска новой работы. А с новыми RFC этот «снежный ком» будет только набирать вес и размеры. Противостоять которым будет всё сложнее и сложнее.

А бывает, что в разговоре с коллегой слышишь что-то типа: «я как не читал документацию и до сих пор не вижу в этом смысла». Задаешь ему вопрос «какой будет результат?» с примером кода:

<?php

if (false) :
    echo 'one';
else if (false) :
    echo 'two';
else :
    echo 'three';
endif;



и в ответ получаешь «three».

А какой будет результат кода? На PHP не пишу давно, но вообще либо parse error, либо three.

Ошибка компиляции будет, потому как при таком синтаксисе должно быть 'elseif'. Если бы это был простой, без скобочный, синтаксис, то было бы 'three'.

Ide подсветит, зачем себе голову забивать, логично что отвечают что будет three, т.к. никто не ждёт что это идиотский вопрос с подвохом про пробельчик

Согласен, пишу 10 лет на php, но глядя на пример мне даже в голову не пришло, что это про синтаксис.
Зачем такое спрашивать — неясно.

А какой правильный ответ вы ожидаете?
syntax error?
Да. Вопрос из разряда «на внимательность», но эти знания могут и в практике эти знания могут пригодиться.

не могут. эти "ньюансы" пусть решает IDE. а забивать голову подобными "особенностями" полезно только разве что для собеседований с вопросами на бумажке на внимательность.

IDE это хорошо и замечательно. И я прикручиваю к ней сторонние анализаторы кода. И коллегам советую хорошие плагины и настройки, для упрощения жизни. Но «не знание знание закона, не освобождает от ответственности».

Например, IDE может не оказаться под рукой, ушел по SSH на сервер чтобы на горячую произвести изменения «здесь и сейчас» и там у вас vim, или nano.

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

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

Некрофилия какая-то, ssh, vim, php code…

А когда это всё вышеназванное успело умереть?

Это про порядок действий, внизу ответили то что я имел ввиду, есть git и запрет редактировать руками файлы на сервере

чтобы на горячую произвести изменения «здесь и сейчас» и там у вас vim, или nano.

У вас разработчики имеют доступ к ssh прода и при этом им разрешается «на горячую» файлы проекта редактировать?

И системой контроля версий(git, svn и т.п.), как я понимаю, вы не пользуетесь?
А ssh только на прод бывает, или вы тоже ЧСВ поднимаете?

Системой контроля версий пользуемся, и CI, и CD.

Замените слово "прод" на "дев" и вопрос остается. За любую редактуру на горячую надо бить по рукам оленьими рогами.

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

Мое личное ИМХО, не подумайте что я наезжаю, но — так делать нельзя. Это приводит к проблемам при параллельной работе, это приводит к вещам навроде "изменил тут, тут и там в течении пары дней" а в сорсы локальные что-то забыл внести и баг в очередной раз всплывает в новой версии.


А про микросервисы… ну тут конечно все сложней, хотя с повсеместным приходом гипервизоров и докера — иметь точную копию прода уже вполне типичная задача.

IDE может не оказаться под рукой, ушел по SSH на сервер чтобы на горячую произвести изменения

Тогда ошибку покажет сам PHP при запуске этого кода. Если вы редактируете что бы то ни было на горячую и потом не проверяете результат, то проблемы в этом случае это следствие ваших действий, а не чьего-то незнания синтаксиса.

> ушел по SSH на сервер чтобы на горячую произвести изменения «здесь и сейчас» и там у вас vim, или nano.

Последний раз так делал году в 2013. Надо произвести изменения — коммит в Git пожалуйста и деплой, никаких «на горячую»
По ssh надо зайти, чтобы запустить git pull, а не чтобы править код.
Давайте ещё будем спрашивать про порядок аргументов в стандартных функциях PHP.
Это наверное самый адок в php с давних пор…
Я конечно не профессионально пишу на php, скорее уж это у меня больше хобби и все такое, но все же пишу на нем всякие мелочи уже многие годы, но блин до сих пор приходится часто вспоминать или сверяться с хелпом на тему того, в какой очередности в ту или иную функцию передать параметры… ибо однотипность и однообразность в этом плане там даже не ночевала…

Phpstorm показывает, в доку уже можно не лезть.

синтакс еррор это когда он приводит к логической ошибке, которая детектится только во время выполнения, например на баше:
A=1
if [ '$A' == '1' ]; then echo 'True'; fi


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

$someobj->$methodName

, потому что джуниоры этой магии не поймут


Я бы вот тоже попросил так не писать. Из-за подобных перлов потом не понятно где конкретная функция используется: статический анализ перестаёт работать, а если там эта $methodName ещё и создаётся с помощью сложения строк или ещё чего похуже, то и даже простой поиск по коду по вхождению строки может не помочь быстро найти откуда ноги растут у той или иной ошибки. По той же причине я предпочитаю не использовать массивы в качестве callable
Иногда такое всё же нужно, чтобы не городить бойлерплэйты. Но я всё же предпочту через swith прогнать строку, чтобы явно видеть, какие строки к вызову каких методов приводят. А если там нужно 100+ вариантов… Возможно, код уже пахнет сам по себе)
Иногда такое всё же нужно, чтобы не городить бойлерплэйты

Не спорю, вполне возможно, что иногда нужно. Просто в моей практике за последние несколько лет у меня не встречалось случаев, когда использование подобных конструкций значительно сокращало бы количество написанного кода.
Ну, как я уже написал, сам стараюсь избегать подобного. Либо закапывать в недрах ядра, с комментариями — если уж других вариантов нет.
А у меня наоборот, регулярно в проектах встречается DI через конструктор, которое приводит к такому дублированию. Скорее всего, именно для таких случаев этот сахар и придумали.
Всегда было интересно, а в чем прикол без скобочного синтаксиса?

меня даже такое без скобок бесит
if ($num === 1) 
    echo 'one';

Меньше символов, обычно и меньше строк.

Вот не согласен, что меньше символов

так
if (!empty($elements)):
    foreach ($elements as $element):
        // ...
    endforeach;
endif;

или так :)
if (!empty($elements)) {
    foreach ($elements as $element) {
        // ...
    }
}


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

При гуглении нашел единственное пояснение, что мол если писать в одну строку, без отступов, в блокноте, без подсветки синтаксиса, то вот тогда то будет проще :)
НЛО прилетело и опубликовало эту надпись здесь

а я бы просто написал


if ($num === 1) echo 'one';

что совершенно понятно, и не понимаю, что все уперлись в обязательные скобки, слава разработчикам языка, добавляют таки упрощенные конструкции и туда еще пока не додумались сувать никому не нужные скобки {}

Точки останова ставить проще, когда тело и условие на разных строках.

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


$num ? 'asdf' : '3454';

или


$num ?? 'asdf';

Я-то по разному делаю. И периодически огребаю из-за невозможности поставить точку останова или непонимания в каком месте сейчас остановился дебаггер.

Ну, а что говорят "гребатели" на такое? (ну я шучу конечно, имею ввиду людей, кто на вас ругается)


return [];

или они приветствуют только такой код везде?


$map = [];
return $map;

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

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


P.S. История расказанная мне в МГТУ преподавателем, так что истинность не гарантирую.

НЛО прилетело и опубликовало эту надпись здесь

Ну не пишите многострочную конструкцию, пишите однострочную, как в моем примере, она же однострочная…
Я уже выше написал пример сокращений в одну строку, никого ведь они не смещают?


$num ?? 'asdf';

Никто не кричит ведь, где же скобки!!! :)


() => 1;

чтоб написать обязательно вот как-то так (не помню, в последней версии php так можно или еще нет… но js точно никто не кричит)


() => {
    return 1;
};
В своё время PHP от Perl-а отпочковался, теперь к Perl-у же и возвращается. И круг замкнётся.

ПХП к перлу никакого отношения никогда не имел. Откуда вы это взяли?
Если вы про распространенное заблуждение "первые версии пхп представляли из себя набор перл скриптов", то это тоже не так.
https://museum.php.net/php1/

Доллар перед названиями переменных в PHP откуда? Из bash-a?

О мой бог. Слово "if" откуда?
Вердикт: все языки отпочковались от… английсого языка ?


Вы немного путаете inspired by и "отпочковались".

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

ru.wikipedia.org/wiki/%D0%98%D1%81%D1%82%D0%BE%D1%80%D0%B8%D1%8F_PHP

HP development began in 1994 when Rasmus Lerdorf wrote several Common Gateway Interface (CGI) programs in C,[17][18][19] which he used to maintain his personal homepage. He extended them to work with web forms and to communicate with databases, and called this implementation "Personal Home Page/Forms Interpreter" or PHP/FI.


PHP/FI could be used to build simple, dynamic web applications. To accelerate bug reporting and improve the code, Lerdorf initially announced the release of PHP/FI as "Personal Home Page Tools (PHP Tools) version 1.0" on the Usenet discussion group comp.infosystems.www.authoring.cgi on June 8, 1995.[20][21] This release already had the basic functionality that PHP has today. This included Perl-like variables, form handling, and the ability to embed HTML. The syntax resembled that of Perl, but was simpler, more limited and less consistent.[8]


https://en.wikipedia.org/wiki/PHP


Кому будем верить? Учитывая что исходники доступны? )


ЗЫ. создал набор скриптов на Perl/CGI для вывода и учёта посетителей его онлайн-резюме, обрабатывающий шаблоны HTML-документов.


Но даже это никак не подходит под "отпочковалось". Он Решил охуенную проблему и респект ему за это. Но с перлом это связано на уроне "мне не понравился перл"


Хотя никаких перл скриптов в первой версии не было )

const f = () => 42;


и он не поймет ничего. Константа? f это скобки? Скобки стремятся к числу? Что это?

ну вообще да, скобки стремятся к числу. Обычное обозначение функции в великом множестве языков.
Позвольте мне не согласится с автором во всех пунктах данной статьи. И я тоже последние 16 лет ежедневно работаю с PHP.

1. Стрелочные функции.
Идея не меняется, они имеют тоже контекст. Контекст каждой функции заключет в фигурные скобки. Так и со стерлочными функциями.

2. Именные параметры.
С `$` начинается обявленная переменная в памяти, РФЦ вводит `:` как присваивание для будущей переменной. С этим РФЦ есть проблемы, но не одна из них не описанна в этой статье. Например РФЦ включает название переменных в АПИ, что ведет к услажнению рефакторинга, теперь изменить название аргумента функции будет сложнее. Но думаю любая ИДЕ эту проблему решит так что програмисты не особо будут с не сталкиваться.

3. Match
Да, код написанные новым синтаксисом можно уже сделать через switch. Но и switch код легко заменить на if, а while на for. Match всего лишь попытка облегчить код, аналогичный код другими средставми минимум в два-три раза больше, что теоритечески сложнее читать.

4. Сonstructor promotion
Осуждение в статье посторенно на «не возможно догадаться». Я сильно сомневаюсь что читающий код это повар, лесоруб или кто-нибудь другой который должен гадать о написанном. Програмист скорее всего один раз познакомившийся с синтаксимом будет узнавать и понимать читаемое легко. А если представить контекст данной операции, то приемущества видны еще более явно. Давайте просто сравним два аналогичных кода
class Point {
    public function __construct(
        public float $x = 0.0,
        public float $y = 0.0,
        public float $z = 0.0,
    ) {}
}

class Point {
    public float $x,
    public float $y,
    public float $z,
    public function __construct(
        float $x = 0.0,
        float $y = 0.0,
        float $z = 0.0,
    ) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}

ИМХО первый вариант предпочтительнее.
> Догадайтесь, что после знаков "="? Начальные значения свойств? Или дефолтные значения аргументов конструктора?

А какая разница? В контексте конструктора? После "=" это и то и другое. А если что-то еще надо добавляем в тело конструктора.

5. Property write visibility
Хотя тут я соглашусь что синтаксис довольно сорный и не понятный, но не могу согласится что РФЦ и обсуждение проблемы плохо. Проблема в языке есть и это факт. Сеттеры и геттеры это просто язва PHP, который делает код безобразным. Хотя я надеюсь что этот РФЦ отклонят на голосовании, т.к. сегодня это решается статическими анализаторами более элегантно. Все же думаю что обсуждение пойдет на пользу PHP.

Итого
В статье упор делается на проблемы новичком, что довольно спорно, ИМХО.
Новички читают учебный материал, для них весь язык является чем-то новым, а не только новшества новых RFC. Это скорее пробелма более опытных програмистов, которые сопративляются изменениям. Главное чтоб преподователи и менторы этих новычков не преподносили материал вместе со своим субъективным мнением.
То, что вы не видите проблем, не значит, что их нет.
Итак, смотрим внимательнее на Сonstructor promotion.
Предположим мы написали нечто вроде:
class A {
  public function __construct(public int $x, public int $y) {}
}

Значит ли это, что теперь в любом объекте класса A должны быть свойства $x и $y и они обязаны быть типа int? Причем они обязательно должны быть заданы в конструторе?

Да? Прекрасно!

class B extends A {
  public function __construct(public string $z) {}
}

А в объектах класса B будут свойства $x и $y? И какой у них будет тип?

Если да — откуда они взялись? Где они задаются? Как мне их задать в конструкторе? Где проходит их тайп-чек, если я не вызываю A::__construct()? Ах, он теперь неявно вызывается… ну извините, это полная дичь!

Если нет — вы сломали наследование. Вы просто ко всем чертям сломали наследование, на котором держится всё ООП в PHP.

Оба ответа плохие. Это плохой код и ужасная возможность, которой никогда не стоит пользоваться.
Я не понимаю о чем речь. Без Сonstructor promotion это выглядит как
class A {
  public int $x;
  public int $y;
}
class B extends A {
  public string $z;
}

Т.е.
Да. Объекты типа B имеет свойства x & y. Не нужно, меняем видимость __construct(private int $x, private int $y).

Откуда они взялись, ясно откуда. Я думаю вы не до конца осознали что такое Сonstructor promotion. Это не значит что свойства класса будут объявлены только если вызвать конструктор.

Тайп-чек проходит на момент присвоения.
>> не значит что свойства класса будут объявлены только если вызвать конструктор
Именно это и значит, читайте RFC. Вам будет неявно добавлен вызов parent::__construct()
> Вам будет неявно добавлен вызов parent::__construct()

Специально перечитал RFC. Можно ссылочку на это заявление?
Был неправ. Неявного вызова не будет. Но без явного всё сломается.
Не сломается если свойства родительского класса с дефолтными значениями. А не с дефолтными и сейчас сломается. Хочу еще раз уточнить Сonstructor promotion не придносит ничего нового кроме как более короткий синтаксис того что сейчас требует повторять трижды (объявление совйства, аргумент, присваивание свойству значение аргумента).

Это явно указано в RFC и показан пример после слов
> Promoted properties follow a simple desugaring, where the following transformation is applied for all promoted parameters
Если я правильно понял фразу «Не сломается если свойства родительского класса с дефолтными значениями.» то должно быть так:
<?php

class A {
    public function __construct(
        public int $a = 1
    ) {}
}

class B extends A {
    public function __construct(
        public string $b = 'hello'
    ) {}
}

$b = new B();
var_dump($b->a, $b->b);


Но вот результат получается вовсе не тот о котором вы пишите:

Fatal error: Uncaught Error: Typed property A::$a must not be accessed before initialization in /in/kd90M:16
Stack trace:
#0 {main}
thrown in /in/kd90M on line 16

Process exited with code 255.


Код в песочнице: 3v4l.org/kd90M

Не исключаю что авторы в первых бетах реализовали что-то не так. Посмотрим как оно будет дальше. Но пока имеем, что есть.
Логично. Конструктор не был вызван, инициализации свойств не было.
Потому что в аргументах не дефолтные значения свойств, а дефолтные значения аргументов.

Это адский ад.
Коллега пытался сделать акцент на то, что «дешугаринг» должен нас спасти, но не спас.
Коллега пытался сделать акцент на то, что «дешугаринг» должен нас спасти, но не спас.

Нет же. Я такого акцента не делал. Я делал акцент что это сахар и ничего не меняет в работе php. Вот так вы бы написали без сахара, и словили бы туже ошибку


class A {
  public int $a;
  public function __construct(int $a = 1) {
    $this->a = $a;
  }
}

class B extends A {
  public string $b;
  public function __construct(string $b = 'hello') {
     $this->b = $b;
  }
}

$b = new B();
var_dump($b->a, $b->b);
Мда… Я в более спокойной обстановке прочел и RFC, и код потыкал, сравнивая существующие варианты с новыми. Плюс до меня немного дольше доходило «Потому что в аргументах не дефолтные значения свойств, а дефолтные значения аргументов.» в комментарии Альберта

Пардон, я был не прав, но я разобрался, по этому спасибо вам!
Согласен с Алексеем, Сonstructor promotion все таки вносит сумбур.

Давайте сравним два примера:

Здесь у нас после инициализации, объект $b всё таки имеет свойство a, да к нему сразу нельзя обратиться, так как оно не имеет дефолтное значение, и по смыслу должно хранить в себе null, но тип ограничен int.
Но после присвоения ему значения в виде 1, всё встает на свои места.
3v4l.org/1530v
class A {
  public int $a;
  public function __construct(int $a = 1) {
    $this->a = $a;
  }
}

class B extends A {
  public string $b;
  public function __construct(string $b = 'hello') {
     $this->b = $b;
  }
}

$b = new B();
$b->a=1;
var_dump($b->a, $b->b);


Здесь же, мы используем Сonstructor promotion, и после инициализации объекта $b, при попытке присвоить значение свойству a, получаем ошибку. Так как у объекта $b нет свойства а, так как конструктор class A не был вызван
3v4l.org/qKUlV
class A {
    public function __construct(
        public int $a = 1
    ) {}
}

class B extends A {
    public function __construct(
        public string $b = 'hello'
    ) {}
}

$b = new B();
$b=1;
var_dump($b->a, $b->b);

Ммм, читая код, ошибка определяется даже без компилятора — у переменной типа int не может быть свойств a и b. Если же написать $b->a = 1 ошибки нет
Пардон, в конце второго блока, конечно же:
$b = new B();
$b->a=1;
var_dump($b->a, $b->b);

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

"Опытные разработчики" это от слово "опыт" или "пытка"? :) Если первое, вроде ничего странного что не сразу получается с "новшествами" или "новым синтаксисом", потому что как опыт получен в другом. И с этим появится и вопросов не будет.

Скорее, пытаются возмутиться. При таком подходе понимать намного сложнее и дольше.


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

Оно сломалось не при создании класса, а при обращении к не инициализированным свойствам. И это не нововведения PHP 8, а уже в языке есть.
Если вы намерянно в конструкторе потомка не вызываете конструктор предка — то кто ж вам виноват?

Интересно как с этим будет работать например ReflectionClass::newInstanceWithoutConstructor из пакета Reflection. А он много где используется в фреймворках для тестирования.

Так же как и без этого сахара.


<?php
class A {
  public function __construct(public int $p = 1) {}
}
class B {
  public int $p;
  public function __construct(int $p = 1) {
      $this->p = $p;
  }
}

var_dump((new ReflectionClass(A::class))->newInstanceWithoutConstructor());
var_dump((new ReflectionClass(B::class))->newInstanceWithoutConstructor());

object(A)#2 (0) {
  ["p"]=>
  uninitialized(int)
}
object(B)#1 (0) {
  ["p"]=>
  uninitialized(int)
}
Интересная магия. Конструктор не вызывали, но в классе А свойство имеет тип, хотя он описан только в сигнатуре конструктора.

Не магия, а короткий синтаксис. В примере A и B одинаковый код, один написаной с использованием сахара, другой без. Но код идентичный.

Должен быть один способ объявления свойств класса. Иногда мне хочется своими глазами увидеть в исходниках свойства. Теперь буду искать их еще и в конструкторе?

> А какая разница? В контексте конструктора? После "=" это и то и другое. А если что-то еще надо добавляем в тело конструктора.
Вы примерами явно показали, что разница есть.
Должен быть один способ объявления свойств класса.

Это тебе повезло наверное в жизни, ты не читал код где свойства класса объявленны не в начале а между классами, что не запрещено. Я это к тому что в данном случае все дело в code standard, если в команде объявлен стандард что писать свойства в начале класса, то не сложно будет объявить что конструктор надо писать тоже сверху. Это кстати даже в RFC рекомендовано, и возможно появится в документации PHP. Остальное дело привычки. Думаю, не надо из-за своих привычек и желаний не давать другим возможности пользоваться чем-то.

Стрелочные функции отличаются от обычных анонимок:

<?php

$var = 'val';

$fn = fn () => $var; // Переменная доступна без дополнительных действий

echo $fn(); // var



в то время как

<?php

$var = 'val';

$fn = function () {
    return $var; // Переменная не будет доступна, ошибка компиляции. Но если ее прокинуть через use - мы получим тоже что и в стрелочной версии
}

echo $fn();



Это не говоря о том что стрелочные функции не могут содержать в себе более одной инструкции.

У меня опыта значительно меньше, но, как мне кажется, разница значительная.
Так и в чем же значительная разница? Стрелочные функции это синтаксический сахар для очень простых (с одним expression) анонимок где не нужно писать `use`. Да это новый синтаксис, да его надо один раз выучить. Говрить о сложностях понимания думаю неправильно. Через годик, когда фреймворки подтянутся и когда каждый программист встретит парочку раз такой синтаксис, он не будет уже казаться новым и страшным.

Привыкаем, прогрессируем и все будет хорошо не хуже.
$foo = 'foo';
$f = function() {
   $fn = fn() => $foo; // Тоже ошибка компиляции
   echo $fn();
}
$f(); 
> У меня опыта значительно меньше

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

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

С вашего позволения отвечу тут и на соседний комментарий.

Разница в том, что в обычных анонимках мы контролируем процесс передачи контекста в область видимости используя `use`, а в случае стрелки нас этого контроля лишили, прокинув в тело стрелки вообще всё. В каких-то моментах это может быть проблемой. И, повторюсь, одна инструкция на стрелку.
Ну надо уточнить что не «все» а лишь родительский контекст. В моем предыдущем комментарии я как раз показал. То что одна инструкция на функцию это ограничивает юз кейсы для данной функции, толька на те где обычная анонимка слишком громозко выглядит. Например
$positiveNumbers = array_filter($numbers, fn($num) => $num > 0);
$objects = array_map($items, fn($item => new Foo($num));

Пока реальных примеров использования не так много в php, в отличии от других языков. Например я часто использую это в JS, и нахожу это очень удобным и неплохо читабильным. Хотя понимаю, что кто-то другой скажет что читабильность ухудшается.

Имхо, матч — по сути же и есть хитрый Key-Value?


Просто вместо


$x = 1;

return array(1=> 'one', 2=> 'two')[$x]

пишем


return match($x) {
 1 => 'one', 
 2 => 'two'
}

если он там работает так же, как в расте?

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


match($action) {
  1 => $this->save(),
  2 => $this->delete(),
}

match(true) {
  $this->canSave() => $this->save(),
  $this->canDelete() => $this->delete(),
}
Если использовать функции в качестве аргументов, то в случае с массивом все значения будут вычисляться

Значения будут вычисляться, когда вы функцию вызовет.

В случае с массивом, всего его значения будут всегда вычисляться во время создания массива, в отличии от match, где будет вызываться та функция, которая соответствует условию match

Не понимаю.


$actions = [
 1 => function () {$this->save();}, // [$this, 'save()'] вариант
 2 => function () {$this->delete();},
];
$actions[$action]()
Только один раз вызовется
А если не каждый элемент функция? Или $action = 3? Больше писанины. Match лаконичнее, без всяких дополнительных переменных
3. Match
Да, код написанные новым синтаксисом можно уже сделать через switch.

Кстати, нельзя. Если говорить о строгой проверке. Есть две вещи, которые заставляли меня ненавидеть swith:
неявное приведение вида
swich(false) {
    case null: echo 'null';
}

и обязательный break, который меня просто бесит. Согласитесь, намного чаще приходится писать варианты, которые должны выполняться по принципу или\или, чем варианты, которые должны выполняться подряд после первого удачного. Я не говорю, что второй вариант не бывает нужен, но мне куда более мила конструкция fallthrough из Go.

И если вторая проблема решается большим бойлерплэйтом, то первая решается только заменой на if elseif elsif elsif…

Обычно матчи ещё выделяются exhaustive matching'ом, что их сильно отличает от свитчей. Как в пхп сделали, правда, не в курсе

В РНР принципиально невозможно такое сделать. Потому что классы (enum нет, для чего еще exhaustive матчить кроме как их иерархии не знаю) могут подгружаться динамически. Пока не обратишься к классу, его в пространстве нет.
Я был рад, что он далек от JS, где принцип читаемости кода был отринут в пользу «пиши меньше символов, всё равно этот код читать никто не будет».

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

Я согласен с автором, что синтаксис большинства сахарков PHP 8 выбран странный и неочевидный. А сами сахарки в большинстве случаев не то что бы сильно облегчали написание кода и могут вызывать путаницу при чтении.
array_fill(value: 50, num: 100, start_index: 0);
Где «доллар»? Нет.

Вообще-то это как-раз логичный компромисс, ибо предполагает отсутствие двойственности при интерполяции того «доллара», чтобы не путать значение переменной с именем аргумента, иначе оно будет смущать еще больше, например что имеем тут:


$name = 'arg';
//test(name: $val);
test($name: $val);

Как это читать? И что здесь передается как имя аргумента, name или arg?
Или может быть это вообще выражение а не именованный параметр, например есть или появится какая-то новая конструкция ($name: $val), типа сахара для (!is_null($name) ? $name : $val)?


Можно было бы сделать что-то типа test($val as $name), но то такое было бы.


Это вообще проблема любого языка в котором изначально некоторые конструкции не предусмотрены, потому не продуманы.
Хотя меня при декларации функций и в некоторых других местах в php всегда тот "логичный и последовательный" доллар раздражал, почему оно не может быть так:


- function test($name)
+ function test(name)

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

Это будет другой язык.

И слава богу…
Язык умеющий и то и то (когда расширение синтаксиса и продуманно и оправдано) только выиграет — например придут новые люди, которых эта "perl-овщина" с долларом всюду и везде ранее смущала или вовсе отпугивала.
Тут как в жизни (только быстрей), если язык не развивается — он стагнирует (и вымирает).

Вы ставите под сомнения значок $.
Помню было много обсуждений на счет него и пришли к выводу что глазу легче цепляться за него.

Без доллара будет путаница с типами, с константами (не зря их пишут капслоком). Доллар улучшает читаемость.
Но в именованных аргументах он действительно не нужен, ибо там передается не значение переменной.
Похоже на нытье олдфага. Пункт про именованные аргументы вообще дичь, причем там $ вообще. Это не переменные, а имена аргументов.

Касательно других пунктов, это все есть в других языках, а не только в JS. Все это есть например в C#. Индустрия развивается, применяются новые «лучшие практики». PHP это уже давно не язык новичков.
целых три способа записи одного и того же
На самом деле два же. Вот эти:
if ($y == 0)
  return 0;

if ($y == 0) {
  return 0;
}
это одно и то же. Почитайте об управляющих структурах.
P.S.: сколькими способами можно обойти массив в PHP?
Два с этим альтернативным. Перечитайте мой комментарий внимательнее.

По сути, но не по синтаксису. Так что способов записи — всё же три

НЛО прилетело и опубликовало эту надпись здесь
Просто проекты становятся всё сложнее, новые запросы (времени и Заказчиков). Языки усложняются. С++ 2a тоже становится всё сложнее. Но что делать? Отменять corutunes? Это не надо драматизировать, просто вопрос привычки.
Так дело-то не в этом.
Я пишу о том, что всё, что добавляется в последнее время — это не новые возможности, это новые способы сделать тоже самое. К трем альтернативам добавляется еще десять. Зачем?

Ну давайте с конкретики. Вот есть паттерн матчинг, сделанный так же, как и в любом другом языке (Java/Kotlin/C#/Rust/Haskell/Scala/...). Вы правда не понимаете, зачем он нужен?

Я где-то сказал, что не понимаю «зачем»? Не приписывайте мне свои домыслы, пожалуйста.

«Зачем» — понятно. Непонятно — зачем столько криво и неконсистентно!

Что конкретно кривого. => вместо двоеточия? Ещё раз: так сделано везде, в сишарпе switch statement пишется как в сишке, через двоеточие, а switch expression (он же матч) — через стрелочки.


Так что вопрос — что кривого и какой вариант "не кривой". И я не додумываю, вы буквально пишете "слишком много способов сделать одно и то же". Ну да, ведь 2+2, 2*2 и 2^2 — тоже слишком много способов получить четвёрку.

Мне не хочется увидеть через год на месте PHP новый Perl. А вам?

Конечно же это плохо, когда из языка делают слонозебродинохрень.


Но я абсолютно не соглашусь с вашим намёком на то, что Perl — это плохо.


Как перл программист (раньше я работал на РНР) скажу следующее:
Перл намного удобнее и лаконичнее РНР

Надеюсь в Шторме уже есть или скоро будет аналогично Андроид студии.
Эту часть можно преобразовать в лямбду в один клик или обратно по вкусу.
Автор ВЫ гений!!!!!!!..
Суть PHP в том что у него был низкий вход. Типа: хочешь начать писать проги, начни с PHP.
но теперь PHP будет иметь высокий уровень. А значит конец эпохи сайтов на PHP.
При всех равных, и уровнях входа, будут изучать только JS. Будут софт писать на нем.
Ооо, похороны PHP. Опять.
Это не похороны, а обсуждение нового сахара в языке
А значит конец эпохи сайтов на PHP.

А звучит как похороны.

Частично согласен. К примеру чужой джаваскрипт довольно сложно читать. С пхп легко… было

Постоянно бесит что тег <?= ?> вызывает ошибку.
Нельзя писать пустые теги <?= ?> так же как с комментариями <?= //$name?>.
ведь одна из задач php быть языком для шаблонов. Т.е. в разметке HTML по вставлять значения. Но тег <?= //$name?> вызывает ошибку. Для отладки приходится использовать <?php //echo $name?> Смысл тега <?= //$name?> теряется.
Я пытался создать дискусию в форуме PHP, но там сложности. Вначале это нужно обсудить, потом нужно еще что то сделать. Прям целый квест. А для начала нужно было инструкцию где то искать как нужно добавлять запросы на функции. С английским я на ВЫ. С переводчиком провалился на регистрации себя на форуме PHP. Думается что я все таки глуповат. но вроде много языков знаю PHP,C#,JS,WPF
Постоянно бесит что тег <?= ?> вызывает ошибку.
Нельзя писать пустые теги <?= ?> так же как с комментариями <?= //$name?>.

Что мешает писать <?= ''//comment?>?
А ответ-то был совсем рядом:
<?php//= $name?>

Или если включена поддержка коротких тэгов, то:
<?//= $name?>

Но в целом — зачем вообще так комментить в шаблонах, раз уж язык используете как шаблонизатор? Какой практический смысл? Есть же дебаггеры.
но вроде много языков знаю PHP,C#,JS,WPF

А что Вы в это вкладываете?
<?= ''; //$name ?>

А на практике необходимость скрывать переменную подобным образом в шаблонах возникает очень редко.
Может быть потому, что с точки зрения интерпретатора это равно коду:
<?php
echo ;
?>

Думается что я все таки глуповат.

Или как минимум не изучили, в чём разница между
<?php… ?>
<?… ?>
<?=… ?>
Хотя это базовый функционал языка, который(особенно если вы не используете сторонний шаблонизатор) стоит знать наизусть.
Т.е. в разметке HTML по вставлять значения.

Я испугался, проверил календарь. А нет, всё нормально. Не 2005-й.


Нет у php задачи быть языком шаблонов. Больше нет. Использовать его так можно, но лучше возьмите Twig, например. Или сделайте клиент-серверное, без шаблонов на уровне сервера.

НЛО прилетело и опубликовало эту надпись здесь
В шоке от изменений. Хоть я перешёл на Go пару лет назад, но за язык с которого начинал обидно… Боюсь через пару лет не смогу прочитать код написанные на 8+ версии.

Если не ошибаюсь, ещё не поздно протащить пачку RFC (кроме стрелочных функций, они в 7.4 приехали) где объяснить как всё сделать правильно. Вот только не просто это будет.


Как вы предлагаете именованные аргументы передавать?


array_fill($value = 50, $num = 100, $start_index = 0);

Так? Так это работать не будет. Не ясно, переменная с присваиванием это или именованный параметр.


Можно конечно не делать ничего, но сама по себе фича очень удобная.


Match действительно нормально бы выглядел как switch:


echo match (1) {
    0: 'Foo',
    1: 'Bar',
    2: 'Baz',
};

Read-write-свойства не могу придумать нормальную альтернативу. Подскажете? Но без них не очень приятно делать DTO. Либо всё public, либо геттеры...


Conditional break-continue-return — нормальный сахарок. Читается однозначно как SQL.

Read-write-свойства не могу придумать нормальную альтернативу. Подскажете? Но без них не очень приятно делать DTO. Либо всё public, либо геттеры...

Мне лично нравится как в JS get property(), хотя там бывает проблема конфликтами если нужно такое же свойство. Вариант в PHP RFC решает эту пробелму, но так и вижу себя постоянно открывая доку ПХП чтоб вспомнить очередность get/set или set/get видимость :D

Да ладно, set-get — противоестественный порядок. get-set же :)

А конструктор перед get? У меня большинство сеттеров, если до них доходит дело сразу после конструктора. Они даже визуально похожи.

На мой взгляд, наиболее аккуратно бы выглядело read-write если бы реализовали аналогично C#:
public int readOnly { get; }
public int age { get; set; }
public string name { get; set; } = "Jane"; 
Можно конечно не делать ничего, но сама по себе фича очень удобная.

Это "удобная" фича сделала имена параметров частью публичного апи, теперь чтобы исправить опечатку в названии параметра нужно будет выпустить новую мажорную версию. Вариант с array_fill(50, default, 0); был, кмк, лучше.

НЛО прилетело и опубликовало эту надпись здесь

Так нету этой необходимости, php storm давным-давно умеет вот так:


image


vscode сразу из коробки так не умеет, но вон там https://github.com/microsoft/vscode/issues/16221 вроде есть плагин.


Для каких-нибудь gd функций оно возможно актуально (даже не вспомню где еще есть по 10 параметров?), но для обычного кода оно не нужно, а если нужно, то это скорее повод задуматься о том что пора что-то отрефакторить. Поэтому, кмк, недостатков гораздо больше чем достоинств (подробнее ниже написал https://habr.com/ru/post/511266/#comment_22276484)

НЛО прилетело и опубликовало эту надпись здесь
Больше всего боялся вот этого wiki.php.net/rfc/php8/merge_member_symbol_tables, пришлось бы оставаться на 7-м, а после отмирания пакетов уходить из профессии просто)

В добровольном сахаре ничего страшного нет по-моему. А с публично-приватными этими перемудрили капитально, чего просто было не сделать ключевое слово readonly?

Потому что оно может быть не readonly (меняться внутри класса не в конструкторе).

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

В одном случае явно перечисленное, а в другом явно всё

Это явно не в PHP — вы язык перепутали.

а мне нравится

Мне тоже нравится!

array_fill(value: $value, num: $num, start_index: $index);


именованный аргумент здесь — не значение переменной, а продолжение идеи type hinting. IMHO, разумеется.


По поводу остального частично согласен, частично нет, но в комментарий не влезет (да и ненужно это).


Я бы не отказался от scala-style case'ов, чего-нибудь в таком духе.


$v = switch ($i) {
case '1': return 42;
case '2': return 55;
default: return 50;
}

… и единообразия именования функций. strlen vs str_replace. Оччень предсказуемые имена. Дэти, это нэвозможно понять, это нужно запомнит! (с)


Но не писать же врапперы вида Str::length и Str::replace?

угу. И то же самое для массивов, файлов итд. Для всех сущностей.

Было много жалоб на увеличение количества фич, а соответственно усложнение порога входа. Вот моё мнение по этому вопросу:


  1. Если Вы пишите на языке (любом) одни, можно писать в старом стиле. В этом случае новый синтаксис не увеличивает порог входа, т. к. никто не заставляет Вас использовать его. Чужой код Вы не редактируете.
  2. Если Вы пишете в команде, значит, с большой вероятностью, Вы пишете профессионально, а значит, во-первых, Вы должны профессионально знать язык, а во-вторых, весь новый синтаксический сахар принесёт намного пользы, чем заберёт времени на изучение, т. к. раз Вы пишите профессионально, значит пишете много, и изучение с лихвой окупится. Как итог, в таких условиях синтаксический сахар — однозначная польза.
  3. Третий вариант — Вы пишете в команде, но при этом непрофессионально и очень мало. Например, Ваш основной язык совсем другой, но Вас попросили помочь на том языке, который Вы знаете плохо. Лично мне такая ситуация кажется странной — зачем просить помогать человека, у которого совсем другая специализация. Но если вдруг такая ситуация возникла, синтаксический сахар нанесёт вред Вам, т. к. увеличит время изучения языка.
  4. Четвёртый вариант — Вы просто играетесь с языком, например, нашли какой-то скрипт, и решили чуть подправить его или исправить баг. Язык при этом учить Вы не хотите, разве что поверхностно. Программировать на этом языке Вы тоже не собираетесь. Здесь обильное наличие возможностей также нанесёт Вам вред — Вы либо не сможете отредактировать чужой код, либо придётся потратить больше времени на изучение языка.
  5. Пятый вариант — Вы зачем-то хотите стать профессионалом в очень большом количестве языков, и Вас расстраивает их сложность.
  6. Шестой вариант — Вы учитель, и хотите как можно больше сократить свою работу.

В итоге во 2-м случае однозначная польза, в 3–6 — вред, в 1-м — нейтрально. Лично я считаю, что в среднем достоинства 2-го случая значительно перевешивают недостатки 3–6 случаев, а значит новые полезные возможности, позволяющие писать более читабельный или красивый код, либо упростить написание кода — это хорошо.

НЛО прилетело и опубликовало эту надпись здесь
Наибольший кандидат на использование — ситуации когда мне нужно в array_map или другую подобную функцию передать calback использующий несколько только что объявленных переменных. И тут уже экономия не только в сокращении function -> fn, тут намного более ценная для меня экономия на бессмысленное перечисление этих переменных в use().
НЛО прилетело и опубликовало эту надпись здесь

Стрелочные функции — это в первую очередь про возможность функционального программирования. Без них это практически нереально (код выглядит ужасно).

Стрелочные функции — это в первую очередь про возможность функционального программирования.

С какого боку? Функциональное программирование — это в первую очередь про аппликацию и абстракцию. Первое, переводя на человеческий язык — это возможность вызвать функцию, а второе — определить эту самую функцию высшего порядка.


Стрелочные функции же, это всего лишь возможность выразить лямбда-терм λx.x через fn ($x) => $x без явного определения свободных переменных через передачу по ссылке или глобальных переменных. Т.е. просто синтаксический сахар для уже существующих конструкций времён самых ранних версий пыха (когда там появился callable тип?).


Более того, т.к. в PHP скаляры не представлены в виде I-комбинаторов, то ни о каких реальных функциональных подвижках вперёд говорить не имеет смысла. Ну и тоже самое касается и операторов языка (т.е. вот этого RFC: https://wiki.php.net/rfc/operator_functions).

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


//Умножаем все элементы массива на 2:

//Со стрелочными функциями — всё норм:
a = a.map(v => v * 2);

//Без стрелочных функций выглядит просто ужасно, это не функциональное программирование, а уродливая фигня:
a = a.map(function(v) { return v * 2; });

Т. е. как минимум в JS без стрелочных функций никуда. В PHP не знаю как.

НЛО прилетело и опубликовало эту надпись здесь

Особенно он хорош по мере усложнения логики, когда не надо ломать голову как её описать в виде комбинации кучи стрелочных функций с методами массивов.

времён самых ранних версий пыха (когда там появился callable тип?).

Появился он в 5.4, в 2012. Но ФВП были в 3-й версии (раньше не застал и нагуглить быстро не получилось), например семейство array_*, просто передача колбэка осуществлялась строкой с именем функции.

НЛО прилетело и опубликовало эту надпись здесь
просто передача колбэка осуществлялась строкой с именем функции.

Ну строка и есть callable. Я имел ввиду не сам тайпхинт "callable", а именно поведение: способы, позволяющие ссылаться на функции.

Спасибо за мнение, на PHP тоже давно и… я не вижу никаких проблем. Язык развивается, приходят новые люди и появляются новые запросы. Я рад такому сахару, для меня он естественен, но я так же немного работал и с JS, Dart, TypeScript, Kotlin, C#, Go. И почти все новое, я уже видел и рад внедрению. Да это вносит кое какие разногласия, но я считаю, что программист должен интересоваться другими языками и всегда изучать новые конструкции языка. Консерватизм до добра не доведет :)

P.S. Жду в PHP 9 дженерики, больше сахара и может быть async.
Уже который год идет деградация(не только в PHP), программистам со стажем нужно смириться с пандемией и сохранять последние нормальные исходники. Никому кроме программистов со стажем не нужен надежный и простой язык программирования — потому что если все работает без багов, то зачем платить ЗП: менеджерам, консультантам и всем кто живут около багов в ПО. Когда есть баги — можно переписать на другом языке или урезать ЗП, нанять новых програмистов и т.д., причин много, но когда багов нет — нет движения денег с одного кармана в другой :) В конце — от сахара станет очень плохо всем. Когда много сахара, то большинство программистов перестают думать и переходят в разряд потребителей сахара.
Господи. Стрелочные функции замыкают на себя весь контекст, потому что они реализуют лямбда-исчисление (а точнее бета-редукцию), и это работает правильно. Принцип какой-то там герметичности (вместо чистоты и ссылочной прозрачности) вы придумали сами. () => 42 прекрасно читаемая константная функция, и любому при первом взгляде на неё понятно, что это константная функция; если непонятно, ему вообще не следует пока взаимодействовать ни с функциями высшего порядка, ни с лямбдами. Пайп-оператор вам непонятен, if как expression вам непонятен.

То есть, вы человек, изуродованный PHP до такой степени, что вся отвратительная древняя рухлядь из PHP3 для вас — малина сладкая, а нормальные взрослые языковые конструкции — страшный яд и мука.
Справедливости ради я, даже будучи начинающим адептом функциональщины, тоже не понимаю смысла if как expression. Для простых случаев есть тернарный оператор, по сути тот же if, только без ключевого слова if. А в сложных не принципиально где return писать, конструкция в любом случае будет выглядеть громоздкой.
Автор, вы бы хоть указывали какие из этих RFC приняты, а какие ещё на этапе обсуждения и голосования находятся. Мне лично очень не понравился синтаксис из RFC с несколькими областями видимости и действительно не понятно предложение с return if. Ну так эти RFC и under discussion ещё. И более того первый же коммент про public:private говорит о том, что синтаксис не интуитивный и предлагают обсудить альтернативы. return if же был ещё только-только в мае опубликован. Для PHP постоянно публикуется куча всяких RFC и если о каждой пачке RFC с кривым синтаксисом делать пост и панику разводить, то можно весь хабр ими завалить и к 30 сесть на успокоительные.

Я думаю что дело в "культуре изменения" — нам внушают и мы в конце концов сами начинаем думать, что если проект не изменяется от мертв.


Это в силе не только для языков но и для произвольного ПО.


А почему нельзя просто сделать хорошее ПО, пофиксить баги и перевести его в режиме поддержки? Если какой-то проект сделает так, то его сразу перестанут пользоваться.


Я часто читаю "Этот проект не обновляется уже два года, значит мертв". А почему не допустить, что просто нет нужды в обновлениях? Баги пофиксены, программа делает то, для чего была написана. Делает это хорошо и быстро. Зачем здесь обновлять??? Сделать глючной и медленной что ли? Чтобы потом все опять фиксить и оптимизировать?

А почему нельзя...
Потому что эффективным менеджерам тоже надо кушать…

Например в зависимости давно найдены уязвимости, они уже обновились, а проект — нкт

ужас. Они превращают php в perl6(aka raku). Там тоже завезли этого «сахара» с горкой.
Выше johnfound правильно написал.

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

Вспомните php5, когда шла разработка php 6.0 несколько лет, и ничего не происходило в комьюнити. Было скучно, было не интересно, из за неразвития языка, многие перешли на другие языки.

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

Результат — сейчас точно нельзя сказать что язык умирает.

Да и на фоне кучи подобных RFC — всегда найдется несколько интересных, в которых действительно хорошие вещи будут предложены и реализованы.

Выше johnfound правильно написал.

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

В тот момент, когда «действительно очень нужно», меняться уже поздно.

Дело не в "движухе", а в том, что новые версии тупо удобнее, причем ощутимо.


Попробуйте откатиться на 3-4 версии языка и попробовать им попользоваться. Ну да, вроде все можно запрограммировать, но выглядит всё некулюже и неудобно

Тут много причин, и «движуха» — тоже очень нужна.

Но вообще, несколько проектов у меня до сих пор на 5.х и да, непривычно на нём писать, после того как основной — на 7.х

Есть ещё один плюс в этих новых изменениях — эффект новизны. Нет ощущения что ты делаешь одно и тоже уже который год ( у меня опыт работы с 2001 года примерно, с пхп 3) — постоянно что то новое
Меня в PHP последние годы тяготит обилие инфраструктуры необходимой для подъема до момента, когда заработает хеловорлд. С одной стороны достаточно
<?php ...;
, а с другой сейчас так не пишут, нужно установить пакетный менеджер, достать кучу компонентов, актуальных под сегодняшние реалии, связать все это, настроить процессный менеджер, настроить веб гейтвей, способный работать с процессным менеджером по его протоколу. На эти минимально необходимые вещи уходит масса времени, которое я хочу тратить на сам продукт, вот в эту сторону надо копать. Остальные языки программирования общего назначения уже решили проблемы инфраструктуры, включив эти инструменты в стандартную поставку и библиотеку. Установил, написал код, все работает. В пхп каждый новый проект перепрыгивать через дом надо, бесит уже.
НЛО прилетело и опубликовало эту надпись здесь
А вы сами пробовали дебаг сервером пользоваться? Чуть отходишь в сторону и уже нельзя работать, он подойдет разве что для раннего протопипирования и проверки гипотезы, но ни в тестах ни в разработке пользы от него чуть более чем никакой.
Отлично он себя в разработке показывает, https правда не хватает.

nginx как терминатор и самоподписанный сертификат рулят )

Ну это уже не так просто, как
php -S localhost:8085 -t ./public

Они запускаются один раз и проксируют трафик на localhost:8085, который запущен вашей командой

Откройте для себя devilbox.
Мне кажется автор за 16 лет порос жёсткой оболочкой, и весь пост о том что раньше трава была зеленее и небо голубее. Это делается не потому что «кто-то» увидел в Python такое, а для того, что бы язык был современым и переход с любого другого языка был максимально мягким.

Ещё сильно возмутило высказывании на счёт const f = () => 42;, что тут не понятного? Отсуствие IQ у отдельного индивидума не говорит об обществе в скупе. Давно стал замечать, что именно преподователи не любят новинки и тянут свои морально устаревшие устои в общество

Читая обсуждение, понял ещё одну перспективность языка php.
У php-программистов, оказывается, много свободного времени.

15 лет назад я пришел в PHP из Дельфи/Паскаля. И тоже плевался: «Это что за херня? Одни скобочки! Где бегин-енд??? Ничерта же не читаемо!». Я до сих пор перед использованием цикла for должен гуглить как он, мать его, пишется. Не могу запомнить где и какие ";" там надо ставить. Это тоже «слом» логики языка, с фигали ";" стоит в середине оператора, а не в конце?
Сейчас я изучаю C# и там пошли еще дальше, там не сократили function до func, там его вообще нет! Просто пишешь возвращаемый тип и имя! Никакого «function» вообще, Карл!
А на прошлой неделе я наткнулся на аналог оператора "??". Но он пишется вообще не так! Спрашивается, какого хрена ПХПшники нагородили свое написание, когда в Си-семействе такой оператор уже был?!(ну или не был, это не важно, важно то, что с какогото хрена нагородили разных выриантов в родственных языках)
Короче, люди ничерта не учатся, и с языками программирования повторяется ровно таже ситуация, что и с языками разговорными — все выпендриваются и специально назло мамке отмораживают себе уши, придумывают правила специально не такие как у соседей.
Почти каждый обсуждаемый для PHP 8 RFC несет одну и ту же проблему — нарушение ранее сложившейся системы языка. И это плохо. Это ломает мозг и тем, кто пишет на PHP давно, и тем, кто только начинает его изучать.

Мир меняется, мир уже не такой как был в 2004 году! Так в нишу PHP пришел Phyton, а пришол он как раз потому, что PHP долго стоял на месте! Сейчас, если PHP так же и останется в 2004 году, то не долго осталось ждать до его смерти, я в этом убежден!

Далее добавляем понятие «замыкания». …

Замыкание— функция первого класса, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции в окружающем коде и не являющиеся её параметрами. Говоря другим языком, замыкание — функция, которая ссылается на свободные переменные в своей области видимости.
Т.е. это функция с доступными ей переменными из внешнего пространства. В PHP переменные из внешнего пространства в анонимную функцию мы передаем с помощью оператора use, поэтому анонимную функцию и называют замыканием.

А дальше у нас появляются стрелочные функции. И это ломает всё.

Все что сделали, так это убрали use и сделали доступными переменные из внешнего пространства по умолчанию, при этом само внешнее пространство стрелочная функция не меняет.

Где «доллар»? Нет.

Как много ругани я читал про то, что PHP плохой язык именно из за знака $, к константам без знака $ как то привыкли.

это новые match-expressions. Можете объяснить, почему в них используется символ "=>", а не привычный по switch-case ":"? И я не могу.

А разве switch-case удалили или объявили как deprecated? Это просто новая конструкция, если вы не хотите применять новые конструкции, то никто вас и не заставляет.

Ну а далее могу просто сказать — можно меняться в угоду привычкам, а можно меняться в угоду лучших решений. Изменения принимаются путем обсуждения, споров и голосования!
Да, возможно что то лишнее появляется и непонятное, но
  1. Это больше дело привычки, человеку всегда сложно отказываться от старых привычек и завести новые
  2. А может стоит сейчас попробовать как можно больше, посмотреть эффективность тех или иных инструментов, исправить ошибки, а потом вычистить все от хлама? Только ведь пока не попробуешь сложно понять что хлам, а что нет

Небольшое замечание, стрелочные функции захватывают не ВЕСЬ контекст, а только переменные, явно используемые внутри функции.
Например следующий код работать не будет:
$name = 'value';
$value = 'value';
$fn = fn() => $$name;
echo $fn();
Больше, больше способов сделать то, что делалось и раньше без всяких проблем

Ох уж этот парадокс Блаба!
это новые match-expressions. Можете объяснить, почему в них используется символ "=>", а не привычный по switch-case ":"? И я не могу.

Потому, что это не разделитель пары "ключ => значение", а разделитель пары "запрос => результат"

Похоже, что с тех времён, когда я соскочил с PHP (4-ая версия на тот момент), язык идейно не особо преобразился в лучшую сторону — непонятное нагромождение не особо консистентных вещей, сверху густо приправленных сахарком)
Какой-то мрак и грусть)
Похоже

Вы делаете вывод о современном состоянии языка по опыту десятилетней давности, когда язык был другим. C тех пор он изменился очень сильно, в лучшую сторону.
Кстати, заметил закономерность, что хоронители php очень часто как раз имели последний опыт с php тех версий.

Процитирую себя 5 лет назад
https://habr.com/ru/post/258767/comments/#comment_8436035
«Наблюдаю краем глаза за лавинообразным развитием пхп последних лет, и сделал парадоксальный вывод. Чем быстрее пхп развивается, тем быстрее он умрет. Очень просто. Из него сделают недо-яву (без юникода, потоков, толковой типизации, тормозную, с «шумным» синтаксисом), и люди получат больше оснований сравнивать.
А сравнив, сделают очевидный вывод.
Процесс запущен.
Мой прогноз: пхп умрет, когда отменят доллар в имени переменных.»

Не согласен. Процитирую себя же:

«Те времена, когда языки программирования отличались друг от друга настолько, что по одной строчке можно было понять откуда она взята — безвозвратно проходят. Сейчас ЯП заимствуют друг у друга все самые лучшие наработки и становятся похожи друг на друга процентов на 80. Конечно чистые ФП или чистые ОО ЯП будут друг от друга отличаться сильно, но внутри одной парадигмы таких отличий будет все меньше и меньше. Поэтому я думаю, что почти все современные популярные ЯП останутся такими же популярными как минимум еще лет 10, и еще как минимум лет десять будут держаться очень так себе прилично на плаву. И, судя по бурному развитию PHP, ближнее и среднее будущее у него безоблачное.
И опять кмк, намного более важным является участие в выполнении интересных и сложных заданий, в результате чего приобретаются универсальные навыки программирования, востребованные в любом ЯП.»

А вот что будет, когда все основные ЯП (в каждой из парадигм ООП и ФП) станут похожими друг на друга процентов на 90, вопрос действительно интересный… Может остануться только два языка — универсальный-оо и универсальный-фп (имеется в виду бекенд).
НЛО прилетело и опубликовало эту надпись здесь

И JavaScript останется. И Вордпресс, и…

… даже небо?
И даже Аллах!
Согласен с автором на 100%.Сам 15 лет провел на php-проектах.Если все эти нововведения будут приняты жизнь разработчика через 3 года превратится в ад.Вы только представьте себе 5-10 летние проекты на поддержке и еще с этими новшествами.Автор прав.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Сочувствую...

НЛО прилетело и опубликовало эту надпись здесь

Расмус же.

Не, Расмус не был никогда никаким диктатором. Вы с питоном путаете.

Кто то ускоряет процес — «разделяй и властвуй». Наверно где то, PHP начал кого то сильно раздражать своим успехом, и тут же прилетели советники как нужно его развивать в «правильном» направлении начиная с 8.0 версии. Зато как будет удобно!
image

Полностью согласен с автором.
На самом деле, было бы классно, если бы ПХП избавился от ООП и стал бы более функционально-ориентированным, тем более его парадигма областей видимости этому сильно способствует.


Люто согласен с тем, что не надо добавлять разных возможностей делать одно и то же. По этой причине сегодня у плюсовиков модно переходить на чистый Си потому что там очень мало возможностей и из-за этого код получается более однородным.


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


Профессионально этим, я, конечно, уже не занимаюсь, но про новые фичи из 7.х читаю и применяю. Много изменилось в сильно лучшую сторону.


Может быть, сообщество сделает форк?

У «С» возможностей больше чем у «С++» при том, что код более простой и работа приложений быстрее. Єдинственная проблема в «С» — нет книг с толковым изложением его возможностей и правильного использования. А также «С» нужно в обязательном порядке изучать с "Assembler" показывая их связность. Базовые языки для изучения «PHP» + «С» + «Assembler», далее можно учить что угодно и что вам нравиться, но не понимая базовых принципов — «Станете всезнайкой — который любит сахар».

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


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


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

Вам просто нужно задать правильный вопрос: почему нет встроеннго типа «строка»? (может нужно изучить «С» и понять истину?), а кто мешает вам написать свой менеджер «алокации» памяти?(может когда его напишете, то еще больше узнаете как работает «С»?). И потом у вас не будут возникать вопросы о работе с указателями. Я же говорю:
Базовые языки для изучения «PHP» + «С» + «Assembler», далее можно учить что угодно и что вам нравиться


Будет полезно посмотреть:
Добавлю свои пять копеек (сам периодически балуюсь с php начиная с версии 5, 2 года писал по работе, как раз когда вышла 7 версия — улучшения были колоссальные):
— именованные параметры — ок, будет удобнее, а то раньше приходилось для повышения читабельности вместо
some_function(24, "ACTIVE", true, true, false);

писать как-то так
some_function($size=24, $status="ACTIVE", $saveToDB=true, $sendNotification=true, $sendSMS=false);

— constructor_promotion — ок, меньше кода писать, удобнее. Хотя ИДЕ умеет генерировать, но всё же
— property_write_visibility и conditional_break_continue_return — сомнительно, но имхо их вряд-ли примут
— стрелочные функции — ок. Правда, я так и не придумал, где это реально будет удобно и полезно. Так же не встречал прям вот красивого и реально удобного применения лямбд ака замыканий ака анонимных функций. Если кто-то покажет красивые примеры — буду благодарен.
Удивительно, что вы ничего не пишете про синтаксис и механику работы атрибутов, который едва успели принять
<<ExampleAttribute>>
use Opcache\Jit;
class Foo
{
    <<ExampleAttribute>>
    public const FOO = 'foo';
 
    <<ExampleAttribute>>
    public $x;
 
    <<ExampleAttribute>>
    public function foo(<<ExampleAttribute>> $bar) { }
}
 
<<Jit>>
function foo() {}

как тут же ринулись голосовать за укорачивание до @@Attr или #[Attr].

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

use Php\Attributes\Deprecated;
use Php\Attributes\Deny;

class Foo
{
    <<Deprecated()>>
    const BAR = 'BAR';
}
 
echo Foo::BAR;
// PHP Deprecated:  Constant Foo::BAR is deprecated in test.php on line 7

<<Deny("undeclared_variables")>>
function foo() {
    echo $foo;
    // PHP Fatal error:  Uncaught TypeError: Access to undeclared variable $foo
}

Директвы препроцессора в си — это почти всегда плохо, говорю как сишник. Не понимаю, как это можно любить. Старый код посмотреть, там раньше еще спецификатор "register" везде пихали.

Директивы препроцессора в C — это некая хрень, предназначенная для компилятора. Тут скорее предлагаются аннотации, как в Python, Java, C# и т.п.

И их может обрабатывать сама программа.
Покажите гению, не знакомому с JS, текст

const f = () => 42;


и он не поймет ничего. Константа? f это скобки? Скобки стремятся к числу? Что это?

Я всегда был рад, что PHP далек от того, чтобы принести в жертву читаемость кода в угоду краткости. Я был рад, что он далек от JS, где принцип читаемости кода был отринут в пользу «пиши меньше символов, всё равно этот код читать никто не будет».

Слишком уж категорично.
В математике есть такая нотация для функций: `f: х -> x + 5`, в JS это будет выглядеть как `х => х + 5`
Так что насчет «гений не догадается что это значит» вы загнули.
К тому же, тут дело не в количестве символов, у стрелочных функций немного другое значение чем у «обычных», у них this не зависит от контекста вызова.
Порог вхождения после принятия сахара
НЛО прилетело и опубликовало эту надпись здесь

Это не "новые фичи", а просто одни из сотен RFC, которые либо действительно примут, либо не факт что примут. И если примут, то не факт, что в таком виде.

НЛО прилетело и опубликовало эту надпись здесь
return if ($divisor === null || $divisor === 0): 0; — ненужная хрень

Это первый шаг к превращению конструкций языка в выражения. И, в целом, это не так уж и плохо. В колтине, например, такой подход используется повсеместно и это реально удобно.

НЛО прилетело и опубликовало эту надпись здесь

Что логично, ибо это по сути своей goto. Может не будем до абсурда доводить?

НЛО прилетело и опубликовало эту надпись здесь

Самое интересное, что можно. Если язык ленивый и поддерживает достаточно абстрактную систему типов.

Единственно непонятно зачем. Без изменения самой сути return'а как jump оператора — это довольно бесперспективное занятие. А с изменением — так лучше его тогда и обозвать по другому.

Ну например чтобы вы могли делать early return, не проектируя функцию под это явно.

Это уже вопрос терминологии на самом деле. Истинный return то всё равно ничего вернуть не сможет. :)

Хотя да, вы правы. Интересная концепция — как-то не думал о таком раньше.

НЛО прилетело и опубликовало эту надпись здесь

Ну всё просто же. На примере простого кода, вот допустим у нас есть такой код:


if cond {
   x = callExpensiveFunction();
   return bar(x);
} else {
   return somethingElse();
}

В строгих языках это не то же самое что


x = callExpensiveFunction();
return cond ? bar(x) : somethingElse();

В итоге сам факт того, насколько дорогая та или иная операция накладывает отпечаток на сам флоу. Вы не имеете права делать некоторые действия в некоторых местах, потому что поток программы идёт сверху вниз. То есть некоторые вещи не инкапсулируются иногда даже не потому что язык этого в принципе не позволяет, а по причинам производительности. А в ленивых языках мы такое сделать можем, и в производительности ничего не потеряем.


Другой пример, допустим, мы хотим собрать преэлементы некоторой последовательности, пока элементы меньше некоторого N. В хаскелле мы так и пишем:


myTake items = foldr (\x xs -> if x > 10 then [] else x:xs) [] items

А как оно будет работать для бесконечной последовательности? А очень просто:


main = print (myTake [1..])
// > [1,2,3,4,5,6,7,8,9,10]

Теперь давайте возьмем другой язык и попробуем там написать то же самое…
И не получится, потому что с точки зрения языка энергичного левая и правая свёртка это одно и то же, поэтому там есть всего один фолд. Возьмем сишарп:


static IEnumerable<int> MyTake(IEnumerable<int> items) =>
 items.Aggregate(
  Enumerable.Empty<int>(), 
  (xs, x) => x > 10 ? Enumerable.Empty<int>() : xs.Concat(new[] {x}));

Если в списке только элементы меньше 10 то мы получим такой же результат, как в хаскелле. Но если элементов окажется больше, то в хаскелле вычисление автоматически остановится, а в сишарпе ответом всегда будет []. А на бесконечном списке оно просто повиснет (в хаскелле вернет правильный ответ).


То есть чтобы свёртка заработала, нужно писать свою специальную функцию. И так далее и так далее. Как ленивые функции замечательно композируются можно видеть на примере итераторов/стримов/..., их во всех языках делают ленивыми. И насколько они гибче каких-нибудь массивов всем тоже очевидно.


Для того чтобы объяснить как return/while/go (который оператор запуска горутины) можно описать как функции мне придется объяснять использование монад для описания DSL различных эффектов, это немного за рамками комментария. Вот и вот немного объясняется. Но суть остаётся ровно та же.

НЛО прилетело и опубликовало эту надпись здесь

Дело не в отказе от return, Это просто сахар и договорённость. Речь принципиальная в том, чтобы функция например на бесконечной последовательности возвращала осмысленный результат.


Окошко в мир ленивых вычислений можно видеть на примере итераторов, где можно за конечное время проверить что две бесконечные последовательности различаются, но кроме списка значений есть ещё полно других структур данных. Поэтому там и говорят что "In Haskell, control flow is not dictated by the language, but by the data structures used.".


Флоу можно управлять с помощью структур данных.

Я же не написал, что "всех конструкций языка".
Естественно имеет смысл превращать в выражения только конструкции, которые по способны вернуть осмысленный результат и которым, при этом, можно воспользоваться. В частности все conditional сюда вполне подходят, а return нет, поскольку он передаёт управление другому контексту.

НЛО прилетело и опубликовало эту надпись здесь

Если if не выражение, то вы не сможете поставить перед ним return


Собственно на одном ретурн свет клином не сошелся


$a = if($b == 2){
   // someComplexMath
} else {
   // otherComplexMath
}

useResult($a)

А хороша эта запись тем, что мы явно видим, что результат вычислений присваивается в переменную $a и в коде ниже мы понимаем, откуда она пришла — нам не надо выискивать все места, где она присваивается.


Сравним


if($b == 2){
   // someComplexMath
   $a = ...
} else {
   // otherComplexMath
   $a = ...
}

useResult($a)
НЛО прилетело и опубликовало эту надпись здесь

Погодите. Это какой-то сумбур.
return вообще никак не затронут. Это оператор, который кладёт аргумент на стек и возвращает управление вызывавшему контексту. Тут вся суть именно в том, что if превращается в выражение — конструкцию, которая возвращает значение.

НЛО прилетело и опубликовало эту надпись здесь

Оу!
Классический пример недопонимания :)
Вы говорили про конкретный RFC (который скорее всего не будет принят. Я уж точно против проголосую), а я про саму концепцию.

НЛО прилетело и опубликовало эту надпись здесь

Символов не так и много, если ограничиться ASCII. Выбрать однозначность символов (для PHP уже поздно) — ограничить развитие языка.

Мне больше второй вариант нравится. Управляющие операторы на то и управляющие, чтобы управлять последовательностью выполнения кода.

НЛО прилетело и опубликовало эту надпись здесь

Я думал, там предполагается, что $a уже определена. Я в таких случаях явно пишу $a = null перед if.

НЛО прилетело и опубликовало эту надпись здесь
return if ($divisor === null || $divisor === 0): 0; — ненужная хрень

В смысле ненужная? Давайте возьмем раст:


fn foo() -> i32 {
  return if true { 10 } else { 20 };
}

А как ещё? Целый специальный оператор ? заводить? Спасибо, не надо. Тем более он не работает для блока. Хотя мне кажется это они из руби упёрли

А как ещё? Целый специальный оператор? заводить?

Ну так-то с оператором "match" не заморачивались по этому поводу...

ну это скорее иф это сахар для macth { true => ..., false => ..., учитывая сколько лишнего текста, то такое сокращениее имеет смысл.

НЛО прилетело и опубликовало эту надпись здесь
Извините, а не могли бы вы на примере объяснить полезность вот этой штуки с |>? Я не троллю и не издеваюсь: никогда не писал ни на F#, ни на Ocaml, поэтому синтаксис выглядит несколько эээ… странным в смысле weird. Спасибо.
НЛО прилетело и опубликовало эту надпись здесь
обратная польская запись

вот зачем вы на ночь глядя, а?

НЛО прилетело и опубликовало эту надпись здесь

Только зачем тут спец синтаксис?


pipe( Validate , Filter , Prosess , Email , Log )( input )

Как минимум не очевидно в каком порядке будет вызываться. Вот вообще.

Оно нигде не очевидно, пока не прочитаешь документацию. Только в одном случае это библиотечная функция и подсказка показывается при наведении на неё курсора. А в другом — синтаксическая конструкция, для понимания которой надо идти читать спецификацию языка, а потом прикручивать транспайлер, чтобы это поняла не только лишь самая последняя версия браузера. Пока таких особых конструкций для сильно частных случаев не много — всё хорошо, но вскоре С превращается в С++ и в коде становится крайне сложно разобраться даже профи.

После того как я узнал, что такое |> я на 90% уверен, что что input |> Validate |> Filter |> Prosess |> Email |> Log передаёт значение слева направо.

После того как я узнал, что такое pipe я на 90% уверен, что что pipe( Validate , Filter , Prosess , Email , Log ) возвращает функцию, которая передаёт значение слева направо.

А я нет. В |> мне стрелочка подсказывает от начала и до конца. В pipe я, в случае если оно слева направо передаётся, вижу два встречных потока: сначала Validate, Filter, Prosess, Email, Log, а потом input справа перебрасывается в самую левую позицию. Опять же, если сравнивать с Log(Email(Process(Filter(Validate(input))))), то обратный порядок для функций, а потом в прямом input. И ничто не подсказывает, что порядок надо менять. Выглядит как будто он произаольно выбран. Ну или какие-то "левые" принципы применены, типа чтобы удобно было каррировать.

Забавно, что во view.tree стрелочка вам ничего не подсказывает и хотите двоеточие или символ равенства, а тут вдруг подсказывает.

Не помню контекста.

Речь о таком коде: http://tree.hyoo.ru/

tree.hyoo.ru’s server IP address could not be found.

Кажется ваш сайт забанен в Украине.

Это IP гитхаба.


Там такой код
$hyoo_tree $mol_book2
    plugins /
        <= Theme $mol_theme_auto
    pages /
        <= Source $mol_page
            title @ \View.Tree
            tools /
                <= Lights $mol_lights_toggle
                <= Compile $mol_link 
                    sub /
                        <= compile_label @ \Compile
                    arg *
                        compile \
            body /
                <= Source_text $mol_textarea
                    value?val <=> source?val \
                    hint <= source_hint @ \view.tree source
        <= Result $mol_page
            title @ \Compiled
            tools /
                <= Close $mol_link 
                    sub /
                        <= Close_icon $mol_icon_cross
                    arg *
                        compile null
            body /
                <= Result_text $mol_text
                    text <= result \

А ДНС чей, не Яндекса случайно?


Ну вот по стрелочкам я могу понять, что в плагины передаётся тема $mol_theme_auto, в страницы источник или исходник $mol_page, но как-то это смысла мало для меня имеет.

Ага, он самый.


Там на первом уровне и справа от стрелочек — объявления свойств. Слева от стрелочек — свойства вложенных компонент.

Не знал, что если у сайта ДНС Яндекса, то весь сайт тоже заблокирован…


Не понятно, вот конкретно


    plugins /
        <= Theme $mol_theme_auto

Theme $mol_theme_auto — свойство Theme со значением $mol_theme_auto, а plugins — свойство вложенного компонента?

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


plugins — свойство, возвращающее список из того, что в него засунули.
Theme — свойство, возвращающее экземпляры указанного далее класса (обычно вложенного компонента). Локальная фабрика, короче.
Ну а стрелочка собственно "засовывает".

Ну что вам сказать, чтобы не обидеть. Это такой глубоко философский вопрос: почему PHP — не Lisp. Ведь и if же записать как if(условие, первая ветка, вторая ветка);. И классы. И массивы. И вообще всё-всё-всё.

Однако, почему-то, в PHP так не сделано. Не скажите — почему?

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

Сделали бы лисп без скобочек на отступах и давали бы функциям говорящие имена
Такое тоже пробовали. Все эти ML, Ocaml, Haskell… они ведь примерно так устроены. Не взлетает. Сделали плюс-минус то же самое в JavaScript и Rust, но на основе C-подобного синтаксиса — взлетело. Народ хотит фигурных скобочек, однако.

Народ хотит фигурных скобочек
Народ не хотит функциональной парадигмы. Достаточно просто добавить фп-фич в ооп-яп. А незнакомый синтаксис — это такая отмазка, для индусов ленивых.

Единственная ФП фича это ссылочная прозрачность. И если её добавить то язык становится ФП. А без неё — не ФП. Достаточно простая граница.


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

Единственная ФП фича это ссылочная прозрачность. И если её добавить то язык становится ФП. А без неё — не ФП. Достаточно простая граница.
Не все согласились с вашей статьей про простое-ФП (хотя сам я, кстати, сторонник простоты). И я пока не определился, согласен я с доводами ваших оппонентов или нет (там правда и доводов то толком нет, так что можно сказать, что я пока в их поиске).

В любом случае, не значит ли ваше утверждение, что создатели всех этих ML, Ocaml, Haskell ошиблись, создавая исключительно чистые функциональные ЯП, когда можно было просто добавить ссылочную прозрачность в распространенные на то время ЯП?

Кто-то паттерн матчинг и лямбды относит к ФП, но связи никакой
Я вот тот самый кто-то )) надо будет подумать об этом…

upd
В любом случае, не значит ли ваше утверждение, что создатели всех этих ML, Ocaml, Haskell ошиблись, создавая исключительно чистые функциональные ЯП, когда можно было просто добавить ссылочную прозрачность в распространенные на то время ЯП?

Они все ссылочно прозрачные. Остальное — просто машинерия. Хотя например вопрос монад в хаскелле весьма жизненный: если в условном жс вы можете забить на какие-то правила и просто в документации или ещё как-то сказать "вызвайте так а не иначе", то в хаскелле нужно уметь подобные вещи выражать в типах. Иначе язык будет конечно чистым, но ничего полезного в нем сделать не выйдет: ни в базу сходить, ни в редис данные положить.


Ну то есть это утверждение из разряда "операционную систему Linux можно написать на ассемблере". Теоретически можно, практически — не очень. Это мелочи из разряда модификаторов доступов, раздельной компиляции, абстрактных/виртуальных методов и так далее. Можно же все методы иметь публичными и комментариями или документациями писать какие можно снаружи вызывать? Можно конечно. Можно ли убрать фичу анонимных классов и всегда писать именованные? Конечно можно. Но всё это сказывается на эргономике.


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

Спасибо за ответ!

И это кто-то использует? В сишарпе я знаю есть PureAttribute, ни в одном проекте где я работал его не видел. Хотя видел весь спектр проектов, от 2.0 и адо и заканчивая пуллреквестом "вчера вышел неткор 3.1, я вот перевел эти сервисы, посмотри пожалуйста".


Но как начинание, конечно, достойно. И это в целом про ссылочную прозрачность, ага. Так что если вся программа написана в таком стиле — то да, ФП,

НЛО прилетело и опубликовало эту надпись здесь

Ну есть решарпер, который вроде на него ругается и который все равно у всех стоит.

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

Вполне имеет смысл, мне например интересно, когда функционал "нечистый" потому что стейт обновляется или в базу запрос идёт, а когда просто потому что лог пишется.

В ООП это обычно не важно — там от этого абстрагируются. Собственно, что кто-то пишет в лог или кидает эксепшены — никому не интересно, ибо логи пишутся везде и исключение может вылететь везде. Кроме тех случаев, где мы этого не хотим и явно пишем pure и nothrow соответственно.

Там это так не интересно, что я не раз получал баг из-за того что две строчки местами поменял. Будь код в (StateMonad MyState m) => m () я бы такой ошибки не совершил

НЛО прилетело и опубликовало эту надпись здесь

На питоне очень просто говокодить так, что потом это будет относительно читаемо. Причём пальцеджоулей на подобный эпистолярный жанр будет потрачено меньше, нежели при использовании каких-нибудь других многословных (Java/C#/C/C++/PHP/etc) языков. Как следствие — язык обрёл сильную поддержку среди "программистов-любителей", ака сообщества математиков и статистиков (плюс системных администраторов, в область знаний которых входит нынче так же bash и perl). Да причём такую крутую, что даже специализированные языки, вроде R или Julia иногда пасуют из-за огромной, уже написанной экосистемы под "data science".


Это лично моё виденье того, почему именно "питон взлетел".

Python или Visual Basic — это такие «ненастоящие языки» для «нанастоящих программистов». Примерно там же, где и какой-нибудь «язык 1C». И взлетел он там, где людям «нужно быстренько посчитать без вской вашей зауми».

Я сейчас о восприятии, не о реальности.

Вот там да — фигурные скобочки не нужны и даже, пожалуй, вредны… Но туда ФП уж совсем никак не лезет в силу очень высокого порога вхождения…
НЛО прилетело и опубликовало эту надпись здесь

А как в таком синтаксисе будет выглядеть


input 
  |> Validate MyValidator 
  |> Filter (x => x%2==0) 
  |> Prosess 
  |> Email "my@email.com" 
  |> Log ElasicLogger

? Если так же как я написал, то тогда ваша запятая это просто оператор композиции и функция pipe не нужна

Запятая — это разделитель операндов.


const Action = pipe(
  MyValidator,
  Filter (x => x%2==0),
  Prosessor,
  Emailer ("my@email.com"),
  ElasicLogger,
)
Action (input)

И какая сигнатура у pipe? Функции все разных типов, общего только что вход одной функции совпадает с выходом другой.


А ещё вы зачем-то съели аргументы функций Validate и Log, ну да ладно

Сложная. Собственно соответствие входов выходам и чекается.


Я не понял их смысла. Масло масляное какое-то.

export type $mol_type_unary_func = ( ( param : any ) => any )
export type $mol_type_unary_class = new( param : any ) => any
export type $mol_type_unary = $mol_type_unary_func | $mol_type_unary_class

Ну то есть ехал any через any. Это всё же чуть хуже чем полностью статически чекабщиеся сигнатуры.


Я не понял их смысла. Масло масляное какое-то.

Что масло масляное? Например функция Log принимает два аргумента: куда писать и что. Так же с валидациями, чем валидировать и что. Ну и так далее.

Вы зря проигнорировали первую половину файла, на который я дал ссылку — проверка типов именно там.


Какой смысл в отделении валидатора от… функции валидации, а также логгера от… функции логирования?

Вы зря проигнорировали первую половину файла, на который я дал ссылку — проверка типов именно там.

Я, к сожалению, не настолько хорошо разбираюсь в тайпскрипте, но в сигнатурах никаких проверок я не нашел. Ткните, пожалуйста, пальцем, потому что я вижу только Funcs extends $mol_type_unary[], то есть тип у всех аргументов дин и тот же, раз мы их в массив собираем. Ну или покажите, какая ошибка компиляции возникает при
pipe(() => 10, () => "Hello")


Какой смысл в отделении валидатора от… функции валидации, а также логгера от… функции логирования?

Да большой. Например, может быть логгер-агностик логика по определению уровня логгирования и стоит ли вызывать нижележащий логгер. Или преобразование юзерского лога в структурный лог и вызов логгера уже с этим структурированным представлением. Много сценариев придумать можно. Мы например используем фронтенд Microsoft.Extensions.Logging, которому передаются логгеры Serilog

Конкретно на этой строке: https://github.com/eigenmethod/mol/blob/master/data/pipe/pipe.ts#L35



Так скомпонуйте эту логику где-то отдельно, создав свой кастомный логгер. Зачем это делать в каждой точке вызова лога?

Хм, ну тогда это то, что нужно, спасибо.


Но нужно понимать, что в каких-нибудь сишарпо-джабо-котлино-свифтах так сделать нельзя. Всякие подобные тайплевел вычисления прерогатива завтиповых языков, и по странному стечению обстоятельств — тайпскрипта. В том же F# откуда взят оператор нет возможности написать такой pipe. Плюс, |> выглядит на мой взгляд аккуратнее. Хотя тут уже +- одинаково.


Так скомпонуйте эту логику где-то отдельно, создав свой кастомный логгер. Зачем это делать в каждой точке вызова лога?

Ну логгер да, а вот валидатор везде будет свой в зависимости от того, что собственно валидируем.


P.S. было бы неплохо цитатами выделять то, на что идёт ответ.

Это скорее прерогатива тьюринг-полных систем типов. Языков с такими типами много. Тот же D имеет куда более продвинутые возможности.


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

Какие спецоператоры? Его можно самому определить, оператор типа


(|>) : a -> (a -> b) -> b
a |> f = f a

Кстати, а почему бы равенство на типах не определить так:


type Equals<A, B> = 
  A extends B
    ? B extends A 
      ? unknown
      : never
    : never

вместо вот этого странного


export type $mol_type_equals< A , B > =
    (
        <X>()=> X extends A ? 1 : 2
    ) extends (
        <X>()=> X extends B ? 1 : 2
    )
        ? unknown
        : never

У тайпскрипта бестолковая система типов:


Этот хак не даёт тайпскрипту сравнивать типы структурно и ему приходится сравнивать их символьно.

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

Да там с самого начала все было через одно место, раскиданное по куче малопонятных функций которые дублировали друг друга. Хорошо что я перешел 6 лет назад на питон, это было как глоток чистого воздуха в выгребной яме. Нету в пыхе логики вообще, если сравнить с нормальными языками. Хуже может быть только жс, но там уже тайпскрипт рулит, так что пых обречен. Нету никаких причин начинать новый проект на этом недоразумении

НЛО прилетело и опубликовало эту надпись здесь
Попробуйте MyPy. При должном усердии (избегать Any) получается терпимо.
НЛО прилетело и опубликовало эту надпись здесь
Не понимаю, о каком вы валидаторе, MyPy и есть уже написанный валидатор типов.
Чему заказчик сопротивляется: запуску команды pip install mypy на машине разработчика, или наличию меток типов в коде?
public:private int $id;

Это Public на чтение и Private на запись? Я хочу такое в Delphi.

Странно, когда пишу на JS мне весь этот синтаксический сахар отлично заходит. Но я до сих пор не могу себя заставить использовать лямбды и стримы в Java.

Все что уменьшает код, упрощает его чтение.
Как же долго я ждал когда switch или if начнут возвращать значения, как в других языках. Ну почему этого нужно было ждать так долго, очевидная же вещь и польза!
Упрощение лямбд как в js, это же просто спасение, радость для глаз, без этих всяких точек запятых и return и function
Именованные параметры, это же "прощай мозговынос порядка параметров" (f(null, null, null, true))
А на синтаксис обращать внимание я уже давно забил, особенно после перехода с _ на верблюда (так и не понял, почему нужно было на это переходить, но ничего, перешли же, не вымерли), так что просто привыкаю.

НЛО прилетело и опубликовало эту надпись здесь

Ну как же, просто вы меня не правильно поняли…
for ($index = 0; $index < 0; ($index = $index + 1))
for ($i = 0; $i < 0; $i++)
Второй вариант, вроде полегче читать и как-то упростилось, не правда ли?


Между if и ?: не такая уж и большая разница так что странно приводить этот пример на мои слова…
С другой стороны, зачем вы используете инструменты не по назначению? Тернарный оператор служит для упрощенной записи простых (не вложенных, с минимальным "телом") if-else-ов в одну строчку, т.е. вместо 5 строчек вы получаете одну. Просто не используйте тернарный оператор со сложными if-ами (вложенными, большим "телом"). Это все равно, что делать из Elastick базу хранения платежей, или гвоздь забиваете отверткой, а не молотком, а потом жалуетесь, "Что-то фигня получается...". Вы же на С не пишите сайты, вы используете синтаксический сахар (называемый PHP, к примеру), не правда ли? Странно было бы видеть, как вы на php будите писать ОС и говорить, что как-то оно не получается как хотелось бы...

Можно и вложенных, если отформатировать нормально:
    $var = cond1 ? val1 :
           cond2 ? val2 :
           cond3 ? val3 :
           otherVal;
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Мне кажется, что все поняли, что из-за низкого порога входа в тему, программистов стало слишком много. И ринулись повышать этот порог и усложнять все вокруг...

Тут двойной, по-моему, результат: порог вхождения увеличивается, но и удобство для его переступивших тоже увеличивается.

НЛО прилетело и опубликовало эту надпись здесь
Для раскрученного ЯП как раз выгодно постепенно повышать порог вхождения, так как его применимость будет увеличиваться, а новички просто будут вынужденны его учить из-за его уже огромного распространения.
НЛО прилетело и опубликовало эту надпись здесь

Во, юнион типы же завезли. Говорили, что всё из Java слизывается в PHP последние годы, но там их вроде нет ещё.

НЛО прилетело и опубликовало эту надпись здесь

PHP всегда был практичным инструментом.
В каком еще языке программа, выводящая "Hello", пишется как Hello.
Это ж гениально.


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


Есть переменные, константы и final, но указать, что присвоение можно производить только один раз — никак. В PHP8 будут аннотации и подобные проверки удобно будет поручить линтеру.
У меня в js-коде 98% const и 2% let.


Есть подозрение, что «герметичный» контекст у функций потому, что удобный было делать лень, а потом уже совместимость и никак. Но вот, наконец, это решились починить стрелочными функциями.


Новшество с аргументами конструктора — вообще праздник.
Я понимаю, что в джаве, чтоб сделать поле foo полагалось для солидности написать 'foo' минимум 4 раза — поле, аргумент конструктора, и присвоение, а еще геттеры, сеттеры и т. п.
Там всё так, но зачем в другие языки было это копировать?
При том, что в 90% случаев аргумент конструктора попадает в поле без изменений, a в остальных случаях можно сделать фабрику.
В котлине:


class Person(firstName: String)
val customer = Person("Joe Smith")

Let, const — вообще забыл что такое существует.
Есть БД, есть классы — всё константное давно храню там...

Если бы не претензии к match, я бы принял эту статью за чистую монету.

Я профессионально программирую на PHP с 2004 года, то есть вот уже 16 лет на момент написания этой статьи, и продолжаю это делать каждый день

А я где-то с 2006-7, и не согласен — в целом всё радует (эх, дженерики бы еще...), за исключением именованных параметров:


  • Сама по себе проблема больше выдуманная, в нормальным коде функций где больше 4-5 параметров мало, да и IDE давным-давно умеют выводить названия параметров.
  • Названия теперь часть публичного API, а значит чтобы исправить опечатку придется выпускать новую мажорную версию, но
  • Проверка имен при наследовании есть только в рантайме — т.е. при обновлении зависимостей теперь гораздо больше работы ибо придется так же проверять и синхронизировать имена.
  • Ассоциативные массивы при распаковке будут использованы как именованные параметры, что может сломать существующий код
  • Привести код к единому стилю больше невозможно и у нас всегда будет каша из argName, argname и arg_name. Два последних варианта использует сам PHP, а т.к. теперь они часть публичного API то исправлены могут быть только в PHP 9 (т.е. в реальности надежд на согласованное std api всё меньше и меньше).

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

Публикации

Истории