Pull to refresh

Comments 66

UFO just landed and posted this here

Статью не читай — сразу комментируй!

В статье недостаточно ясное обоснование: «невозможно реализовать, путаница с элементами массивов в некоторых случаях».
Кажется вполне очевидно:

$x = 1;
$y = 2;
$arr = [
    ($x) => $x * $y, // дословная копипаста из примера
];
// что мы получим в итоге?
$arr == [1 => 2]; // сейчас будет этот вариант
$arr == [0 => callable]; // так хотите?
Да, я ожидаю второй вариант.
А вот от этого $arr = [(($x) => $x * $y)()] — первый.
Бред какой-то, если по-вашему это стрелочная функция, то вы здесь вызываете функцию от одного аргумента, не передав ей ни одного. Её результат будет соответствовать ключу 0 в массиве.

А теперь подумайте и скажите, по какому контексту транслятор сможет отличать пару от лямбды, кроме случаев, когда ключ — константа?
Ну, хорошо: $arr = [(($x) => $x * $y)($x)].
А теперь подумайте и скажите, по какому контексту транслятор сможет отличать пару от лямбды, кроме случаев, когда ключ — константа?

А, точно. Пардон, я всё время на ECMAScript перескакиваю.
Почему первый? — По вашему варианту, по идее должно получится:
$arr == [0 => 2];

Как минимум — это ломает обратную совместимость. Такой вариант нельзя было впихнуть в 7.4 из-за этого.
Всмысле, вы же сами нарисовали две скобочки — вызов функции. Или что вы имели в виду?
А, индекс 0. Да, я это и имел в виду.
Да, только вы уже сами запутались/ошиблись. Вот чтобы избежать такой неприятности, — так делать не будут.
Очень заметно, когда разработчики языка стараются сделать что-то лучше, но ночью втайне ходят кодить к любов^w^w на JS. А когда-то PHP был простым скриптовым языком, чем многих и цеплял.
А ничего что очень похожий синтаксис используется для лямбд в Java/Scala? Вообще, мне кажется что PHP в очень большой степени вдохновляется именно Java, чего стоит хотя бы Symfony (не скрывается что источник вдохновения — Spring), Doctrine до боли похожая на Hibernate, многие конструкции самого языка (try… catch… finally) и т.д.
try catch finally, если я ничего не путаю, ведут свою родословную из C++ как и в JavaScript / Java / тыщи их
Если я ничего не путаю, finally в C++ раньше не было (может быть в новых стандартах появился, я не слишком слежу за ними).
PHP/FI вас тоже цеплял? Он был очень простой и понятный.
UFO just landed and posted this here
Жалко, что не с той стороны подходят. Все сахарка подкидывают. Лучше бы enum добавили и дженериков.
Вот, кстати, всегда было интересно понять, зачем людям нужны дженерики в языке с динамической типизацией?
1) в php можно включить строгую проверку типов аргументов функций (проверка в рантайме). Ну и IDE тебе подскажет, где ты неправ
2) для читаемости. Т.е. Collection читается хуже, чем Collection<User>

1) При указании типа аргумента/возврата — этот тип жестко прописывается в атрибутах функции на этапе компиляции и проверяется достаточно дешево. Для дженериков придется полностью переделывать механизм проверки, что однозначно не в лучшую сторону повлияет на производительность.
IDE же отлично работает с phpdoc комментариями User[] $users.
2) Не очень удачный пример для языка с убертипом array


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

Да мне кажется, дженерики тоже можно на этапе компиляции проверять. Просто запрещать передавать переменные без указания типа. Типизация же, зачем они нужны. Если надо, можно сделать функцию-обертку, которая будет принимать типизированные аргументы и передавать дальше в дженерик. Чтобы обертки не плодить, можно какой-нибудь оператор типизации придумать, типа $x as User или (User)$x, рантайм-проверка будет в нем происходить.

А он что, мертв? Не то чтобы я любил PHP, но язык очень широко используется и не только в вебе.
UFO just landed and posted this here
Увы, не оскорбил. Но хабр позиционируется как ресурс для профессионалов и культурных людей. А потому троллинг и вбросы тут не приветствуются. Если у вас есть мнение почему похапэ такой плохой, то есть 2 варианта: написать аргументированное мнение или не писать совсем.
да таких аргументированных мнений уже столько было написано — в том числе и здесь на хабре. Смысл все это повторять
Таких неаргументированных мнений и вбросов знаете сколько было написано, в том числе и здесь. Смысл всё это повторять?

Ну да, фейсбук, википедия, вконтакт, Baidu, tumblr, digg, совсем мертвый. И это если не считать всякие вордпрессы и опенкарты.

// так сделано в Rust, но читабельность спорна
|$x| => $x * $y

Спорное утверждение :-)
Для php-шника будет просто непривычно это написание, а не то чтобы нечитаемо. Мы привыкли к скобкам обычным.
Мне кажется с синтаксическим сахаром начинается потихоньку перегиб. Объём синтаксического сахара повышает порог вхождения в язык, которым всегда так подкупал PHP.
Так-то стрелочные функции — это фича, которую очень долго ждали, поскольку классический монструозный синтаксис анонимных функций ну прям вот раздражал жутко.

array_map(function($x) {return $x*$x;}, $arr);

против
array_map(fn($x) => $x*$x, $arr);

Прям глаз радуется.

Да и в любом случае это не совсем сахар — таки замыкание по умолчанию.
array_map(function($x) {
    return $x * $x;
}, $arr);


Честно? — Совсем не раздражает. Это сугубо субъективно, — не имеет смысла обсуждать. Факт в том, что вводя миллион правильных способов сделать одно и тоже — мы получим то, что весь миллион способов будет использоваться. Соответственно для интеграции нового программиста в язык — ему нужно будет учить весь миллион способов.

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

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


Синтаксический сахар, когда он уместен — это крайне полезная и правильная вещь. Посмотрите, например, на успех Kotlin, где сахарок возведен фактически в абсолют. Что касается PHP, то чистого сахара в нем еще поискать надо. Так, на вскидку, только краткий синтаксис массивов вспоминается, скажите еще, что его зря вводили.

Зачем мне говорить, что зря вводили краткий синтаксис массивов? Слово «зря», в этой ветке комментариев, я первый раз употребил только в этом сообщении… Я нигде ничего подобного не утверждал.

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

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

Потому, что это тоже синтаксический сахар.

Кстати, я чего ворчу. Лучше бы придумали, как foreach со ссылками подружить.
Так-то вариант с foreach вполне адекватен:
foreach($arr as &$x) $x *= $x;
unset($x);

Если избавиться от unset, то по количеству символов будет даже короче стрелочной функции. И тут возникнет вопрос, а нужны ли стрелочные функции…
Просто не нужно использовать ссылки в foreach
// нереализуемо, путаница с получением свойств объекта
($x) -> $x * $y
Всегда было интересно, почему в одних языках могут сделать одинаковую работу с внутренностями объекта (независимо от того, указатель это или объект сам), например через точку, а в других языках приходится придумывать несколько разных вариантов?
А в данном случае, что, реально может быть свойство с именем `$x * $y`?
Нет, чтобы было свойство $x * $y — нужно использовать фигурные скобки. В этом же варианте, — сначала будет получено свойство $x объекта $x, результат которого будет умножен на $y.
И да, это вполне рабочий код:
class Test{
        public $test = 2;
        public function __toString(){
                return 'test';
        }
}
$x = new Test;
$y = 1;
$result = ($x) -> $x * $y;
var_dump($result);

Разве не у всех подобное есть в продакшне? =)
чтобы было свойство $x * $y — нужно использовать фигурные скобки
А, ну да, я что-то протупил.
Свойство $x * $y тоже вполне может быть, проблемы будут только с конвертацией объекта в число.
class Test{
        public function __get($attr){
                return '5';
        }
        public function __toString(){
                return '2';
        }
}
$x = new Test;
$y = 1;
$result = ($x) -> {$x * $y}; // Notice: Object of class Test could not be converted to int 
var_dump($result); // 5
$result = Collection::from([1, 2])
    ->map(fn($v) => $v * 2)
    ->reduce(fn($tmp, $v) => $tmp + $v, 0);


И чем это лучше чем

$result = 0;
for ($v = 1; $v < 3; $v++)
    $result += $v * 2;


Вообще ничем, лишние слова map, reduce, Collection, fn, лишний синтаксис, fn, =>, и компактнее код совсем не стал. Нафига козе боян. Простой и понятный язык превращают непонятно во что, только потому что модно, и в других языках есть.
$result = 0;
for ($v = 1; $v < 3; $v++)
    $result += $v * 2;


И чем это лучше чем

$result = 6;


Вообще ничем, лишний for, ++ и *, и компактнее код совсем не стал. Нафига козе боян. Простой и понятный язык превращают непонятно во что, только потому что модно, и в других языках есть.
Именно, что плодить сущности — не всегда хорошо. Можно ведь и так сделать:
 Collection::fromOneAndTwo()
    ->mapQuadFunctionThenReduceToSum()

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

Вот опять — вроде отличная идея, а реализация вносит еще больше хаоса в и без того сумбурный язык. Теперь есть два синтаксиса для анонимных функций: один (как я понял) только для выражений, автоматически захватывает scope и использует одно ключевое слово (fn), другой — для утверждений, захватывает явно и использует другое ключевое слово — function. Оккам смотрит на это решение с недоумением.


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

Вот я за это тоже хотел написать коммент, но долистал до Вашего. Чтобы вводить новое ключевое слово, нужны более веские причины, чем ленивость набрать 6 лишних символов («unctio»). Сделали бы уже таки как в JS, но я там не спец, вроде просто (x) => x + 5 или типа того, если так уж париться за короткий синтаксис анонимных функций. Мне увлеченность синтаксическим сахаром кажется манией, желанием делать что-то с языком чисто для видимости. Есть конечно полезные нововведения (отказ от расширения mysql, нормальное наконец разыменование), но вот это вот всё уже онанизм какой-то :D
ИМХО.

Там не 6 лишних символов, а больше. Есть же ещё return, фигурные скобки и конструкция use.

Может я что-то пропустил, но как быть, если функция многострочная? Или если мне не надо, чтобы она что-то возвращала? Если тело можно обернуть в фигурные скобки, то ОК. А так идея давно назрела, часто проще и быстрее использовать функции типа map/reduce, нежели что-то циклами обходить, но синтаксис передачи функции в качестве аргумента был слишком громоздский.
Многострочные функции — старым синтаксисом, если я правильно понимаю.
да, пока что старым синтаксисом
Вот это самое печальное… Старый синтаксис меня в общем-то не особо напрягал, меня в нем напрягало явно биндить переменные из родительского скоупа, вот с ними периодически все превращалось в полный ад…
Если вам регулярно нужно биндить много переменных из родительского скоупа — я думаю это «запах». Мне обычно приходится биндить не больше 2-3 переменных. И то что они указываются явно — считаю плюсом.
так сделано в языке Hack; но слишком сложно для текущего парсера


Вообще-то нет, LALR всё это позволяет. Аргументация была другой, что это дополнительные нагрузки на lookahead парсинг (т.е. неоднозначность грамматики), тогда как PHP чувствителен к скорости парсинга, а значит профитнее добавлять префикс, вместо суффикса.
кто-то вообще в курсе что это за запись?
`fn&($x) => $x;`
объясните плз

Жесть, ну и синтаксис.
Напоминает МАКРО-11, где можно было


  • mov 10,r0 — помещает в регистр PC+10
  • mov #10,r0 — помещает в регистр 10
  • mov @10,r0 — помещает в регистр значение по адресу PC+10
  • mov @#10,r0 — помещает в регистр значение по адресу 10

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

Довольно логичный синтаксис, кстати. Куда лучше всех этих word ptr [...]. Хотя я бы 10 и #10 поменял местами.

Ну пойдёт, не считая того, что регистр справа, а не слева, как в большинстве. Лично моё ИМХО — мнемонику проще в освоении, чем у Z80, ещё пока не придумали :-)

А i8080 чем не нравится? :)

Sign up to leave a comment.

Articles