Comments 45
UFO just landed and posted this here
То есть у вас основная претензия — это что автодополнение кода не работает?..
+1
UFO just landed and posted this here
По-моему, вы немного не по адресу. В PHP утиная типизация, какого вывода типов вы от него хотите? А делать вывод типов как в примере выше на уровне IDE — это очень сложное и неблагодарное занятие. Я не знаю сред разработки для динамически типизированных языков, которые умеют подобное вытворять (ну, разве что в частных случаях).
+1
В PHP утиная типизацияС каких пор?
0
Вы часто видите типы у аргументов функций? А у результатов функций и переменных? :) Или, может, скалярные типы в type hinting уже поддерживаются? Или вообще, в стандартных функциях «mixed» уже не упоминается?
PHP, конечно, пытается мимикрировать под джаву, но — слава богам! — пока не настолько активно.
PHP, конечно, пытается мимикрировать под джаву, но — слава богам! — пока не настолько активно.
+3
Вы путаете утиную и динамическую типизацию.
0
Утиная типизация — вид динамической, так что автор ничего не путает.
<?php
class Duck {
function quack() { echo "Quack", PHP_EOL; }
function fly() { echo "Flap, Flap", PHP_EOL; }
}
class Person {
function quack() { echo "I try to imitate a duck quack", PHP_EOL; }
function fly() { echo "I take an aeroplane", PHP_EOL; }
}
function in_the_forest($object) {
$object->quack();
$object->fly();
}
in_the_forest(new Duck);
in_the_forest(new Person);
Quack
Flap, Flap
I try to imitate a duck quack
I take an aeroplane
+1
Это умеет IDE, не вижу особо проблем с тем, что бы написать простенький плагин для какого phpstorm с добавлением ресолва типов в замыканиях и для автокомплита.
0
Ну я лично против php внутри строк, тем более что этот тикет никак не повлияет на вашу реализацию. у вас все же синтаксис замыканий не являтся валидным для php. Все относительно конечно, но не вижу особых проблем. А тот тикет — он не нужен никому.
0
Эти строки можно писать по-разному, один из синтаксисов валиден. Можно и добавить альтернативу, например, заменить
PHP в строках — зло, но это далеко не единственная библиотека, которая этим грешит. Какая-нибудь аннотация типа «этот аргумент — код» определённо не помешала бы.
==>
на /**/
. От реализации этого тикета анализа кода в строке не появится, но хоть будет нормальная подсветка и проверка синтаксиса.PHP в строках — зло, но это далеко не единственная библиотека, которая этим грешит. Какая-нибудь аннотация типа «этот аргумент — код» определённо не помешала бы.
0
Выглядит классно, но хотелось бы пару бенчмарков. Сколько времени исполняется ваш пример на тестовом массиве, скажем, из пары тысяч элементов?
0
Вы можете написать аналог на голом PHP для сравнения?
В моих бенчмарках с относительно простыми запросами оверхед болтается между 20% и 200%, в основном 50%–100% (во сравнению с реализацией на циклах). Чем меньше действий происходит в «теле», тем больше оверхед в процентном отношении (на абсолютно голом цикле можно получить 500%). От использования функций на массивах с колбэками скорость тоже заметно просаживается, к слову. Сколько потеряет конкретное приложение — надо смотреть по приложению.
Если память не изменяет, LINQ в .NET тоже просаживает скорость. Какое-то время назад обещали, что заоптимизировали, но не проверял.
В моих бенчмарках с относительно простыми запросами оверхед болтается между 20% и 200%, в основном 50%–100% (во сравнению с реализацией на циклах). Чем меньше действий происходит в «теле», тем больше оверхед в процентном отношении (на абсолютно голом цикле можно получить 500%). От использования функций на массивах с колбэками скорость тоже заметно просаживается, к слову. Сколько потеряет конкретное приложение — надо смотреть по приложению.
Если память не изменяет, LINQ в .NET тоже просаживает скорость. Какое-то время назад обещали, что заоптимизировали, но не проверял.
0
Сахар сахаром, но хранить куски кода в строках — брррррр. Ничего не имею против самой либы, но пользоваться ей (если бы пришлось) я бы стал только примерно так:
Громоздко, сложно к восприятию. Но всяко, имхо, лучше строк.
<?php
$result = from($categories)
->orderBy(function($cat){return $cat["name"];})
->groupJoin(
from($products)
->where(function($prod){return $prod["quantity"] > 0;})
->orderByDescending(function($prod){return $prod["quantity"];})
->thenBy(function($prod){return $prod["name"];}),
function($cat){return $cat["id"];},
function($prod){return $prod["catId"];},
function($cat, $prods){return [
"name" => $cat["name"],
"products" => $prods,
];}
);
Громоздко, сложно к восприятию. Но всяко, имхо, лучше строк.
+2
P.S. Если и так часть кода — это простые function($a) { return $a['fieldName']; } то почему бы не заменить на:
<?php
$result = from($categories)
->orderBy('name')
->groupJoin(
from($products)
->where('quantity', '_ > 0') // это уже фантазии на тему
->orderByDescending('quantity')
->thenBy('name'),
['id', 'catId'],
function($cat, $prods){return [
"name" => $cat["name"],
"products" => $prods,
];}
);
+1
По сути такимо образом пытались видимо обойти то ограничения, что в PHP нету удобного синтаксиса для лямбд. Да и ваш вариант сложнее воспринимать.
0
Первый вариант да, он является полным аналогом варианта из поста (если я правильно его понял). Второй же подход мне видится гораздо симпатичнее.
Для сравнения
и
Уж, думаю, библиотека может выполнить что-то вида
Для сравнения
->orderByDescending($prod ==> $prod['quantity'])
->thenBy($prod ==> $prod['name']),
и
->orderByDescending('quantity')
->thenBy('name'),
Уж, думаю, библиотека может выполнить что-то вида
if (is_string($v)) {
$res = isset($dict[$v]) ? $dict[$v] : null;
}
elseif (is_callable($v)) {
$res = $v($dict);
}
else ...
0
Вы оптимизировали синтаксис под частный случай. :) А если в where мне нужно условие и для значения, и для ключа (массивы в PHP содержат и то, и другое)? А если мне нужно отсортировать по синусу количества? А если ключи массива для соединения вложенные, и вообще это не ключи масства, а свойства объекта или результаты вызова функций? А как мне передать ссылку на именованную функцию (подсказка: в PHP указатели на функции трёх типов: строки для функций, массивы из пары объект-строка для методов, массивы из пары строка-строка для статических методов)? И так далее.
В Ginq есть синтаксис для получения полей из Symfony (и нет строковых лямбд), но эта штука просто космически тормозная — оверхед за 1000% и дальше. И эта штука удобна в join'ах и сортировках, но совершенно бесполезна в select и прочих методах.
В принципе, отдельный синтаксис лямбд для получения полей не лишён смысла, но это надо хорошо продумать, с бухты-барахты это не сделаешь. И уж точно нет смысла менять аргументы у функций, потому что от всех вариантов перегрузок тогда можно будет убиться (и сейчас-то непросто, со всеми этими ключами).
В Ginq есть синтаксис для получения полей из Symfony (и нет строковых лямбд), но эта штука просто космически тормозная — оверхед за 1000% и дальше. И эта штука удобна в join'ах и сортировках, но совершенно бесполезна в select и прочих методах.
В принципе, отдельный синтаксис лямбд для получения полей не лишён смысла, но это надо хорошо продумать, с бухты-барахты это не сделаешь. И уж точно нет смысла менять аргументы у функций, потому что от всех вариантов перегрузок тогда можно будет убиться (и сейчас-то непросто, со всеми этими ключами).
0
Я не знаком с LINQ, оценивал по вами же приведенным примерам :)
>> А если в where мне нужно условие и для значения, и для ключа
>>А если мне нужно отсортировать по синусу количества?
>>и вообще это… свойства объекта…
__get, ArrayAccess,…
>>А как мне передать ссылку на именованную функцию
use(...)? Или не совсем понял о чем речь.
Я к чему это все. Всякий раз сталкиваясь с «yet another LINQ port», не понимаю, зачем настолько досконально пытаться перенести на тот же PHP то, что целиком и полностью завязано на возможностях синтаксиса C#. Почему не продумать альтернативу при похожем подходе с цепочками вызовом?
>> А если в where мне нужно условие и для значения, и для ключа
where(function($k, $v) {return $v['quantity'] > 0 && ($k%2 == 0);})
>>А если мне нужно отсортировать по синусу количества?
orderByDescending('quantity', 'sin(_)')
>>и вообще это… свойства объекта…
__get, ArrayAccess,…
>>А как мне передать ссылку на именованную функцию
use(...)? Или не совсем понял о чем речь.
Я к чему это все. Всякий раз сталкиваясь с «yet another LINQ port», не понимаю, зачем настолько досконально пытаться перенести на тот же PHP то, что целиком и полностью завязано на возможностях синтаксиса C#. Почему не продумать альтернативу при похожем подходе с цепочками вызовом?
0
Сейчас вы начинаете строить в уме трижды вложенные циклы, вызовы функций для массивов
1. А при вызове функций библиотеки сколько вложенных циклов будет? К примеру, в вашем примере какая сложность алгоритма получается?
2. Ведь данные хранятся в БД, соотвественно нужные данные в нужном формате можно выбрать SQL запросом, что убдет явно быстрее чем их обработка на PHP.
3. Интересно было бы посмотреть сравнение быстродействия и используемой памяти:
— Использование SQL запроса;
— Обратботка сущесвующих массивов с помощью YaLinqo (хотя сюда нужно суммировать и выборку данных из БД, потому что вряд ли вы данные храниет в массивах);
— То же самое что и предыдущий вариант, только вместо библиотеки — реализация нанативном пхп под определенную задачу.
-2
А при вызове функций библиотеки сколько вложенных циклов будет? К примеру, в вашем примере какая сложность алгоритма получается?
Математическая сложность алгоритма не меняется. Меняется «логическая» сложность алгоритма. Например, цепочка select-where-selectMany представляется линейной цепочкой вызовов, и человек воспринимает это как простую последовательность трёх операций: преобразовать, отфильтровать, преобразовать со слиянием. Если же разворачивать цепочку в код, то будут вложенные for-if-for-for, которые сильно напрягут мозг и заставят анализировать кучу мусора. join за собой скрывает for-if-for, некоторые больше, некоторые меньше. Последовательные операции в разы проще воспринимать, чем вложенные. Сортировка orderBy-thenBy — проще, чем usort и колбэк с функцией сравнения (кода в три раза больше, распознавать порядок ещё сложнее).
Ведь данные хранятся в БД, соотвественно нужные данные в нужном формате можно выбрать SQL запросом, что убдет явно быстрее чем их обработка на PHP.
Не все данные хранятся в БД. Вы б второй абзац прочитали что ли.
По поводу быстродействия см. комментарии выше.
0
По поводу «логической» сложности полностью согласен. А по поводу математической — нет. Ведь использование дополнительной функции, библиотеки, фреймворка — явно увеличивает сложность. Только что я не много потыкал под xhprof. Вот код с использованием либы, а вот нативный. И результаты:
Нативный:
С либой:
Видно, что с использованием либы — памяти раз в 5 больше и скорость выполнения — раз в 8 и количество вызываемых функциий — раз в 10. Если решать задачу с использованием SQL запроса — то еще быстрее.
Об этом я и спрашивал.
Я не спорю, что нативный код не всегда хорош (не учитывая хайлоад приложения), и подход который предлагаете Вы- явно удобнее и логически приятнее читать, особенно если бы не было лямбда функций в строках, но использование дополнительных библиотек — это всегда жертвование ресурсов, и здесь важно знать, чем ты жертвуешь и в каком количестве.
Нативный:
С либой:
Видно, что с использованием либы — памяти раз в 5 больше и скорость выполнения — раз в 8 и количество вызываемых функциий — раз в 10. Если решать задачу с использованием SQL запроса — то еще быстрее.
Об этом я и спрашивал.
Я не спорю, что нативный код не всегда хорош (не учитывая хайлоад приложения), и подход который предлагаете Вы- явно удобнее и логически приятнее читать, особенно если бы не было лямбда функций в строках, но использование дополнительных библиотек — это всегда жертвование ресурсов, и здесь важно знать, чем ты жертвуешь и в каком количестве.
+4
Идеальный комментарий, который я искал, открывая топик =)
+1
Хм. Расход памяти какой-то конский. Там не должно выделяться столько. Надо глянуть.
Мера О та же самая. Коэффициенты и константы, разумеется, отличаются.
1. Вы неправильно отсортировали категории: отсортировали по и так возрастающему ключу, хотя требовалось по имени. То есть не отсортировали вообще.
2. Вы неправильно отсортировали продукты: отсортировали только по количеству, хотя надо было по двум полям, в том числе по имени.
Собственно, к вопросу о наглядности кода. :)
Если у вас есть база с гигабайтами данных, то использование этой библиотеки — ошибка по определению. Эта библиотека предназначена для случаев, когда SQL нет. Вот вы от веб-сервиса получили сотню записей — вы будете запихивать их в базу, чтобы применить SQL?
Кроме того, что сравнение с SQL идейно некорректно (вы ещё с C++ сравните), оно неадекватно и по другой причине: в реальном коде гораздо больше шансы увидеть толстые ORMы, а не голый SQL. На ORMы все плюются, но пользуются. Здесь примерно та же история.
PHP и хайлоад в одном предложении — признак недальновидности.
А по поводу математической — нет.
Мера О та же самая. Коэффициенты и константы, разумеется, отличаются.
а вот нативный
1. Вы неправильно отсортировали категории: отсортировали по и так возрастающему ключу, хотя требовалось по имени. То есть не отсортировали вообще.
2. Вы неправильно отсортировали продукты: отсортировали только по количеству, хотя надо было по двум полям, в том числе по имени.
Собственно, к вопросу о наглядности кода. :)
Если решать задачу с использованием SQL запроса — то еще быстрее.
Если у вас есть база с гигабайтами данных, то использование этой библиотеки — ошибка по определению. Эта библиотека предназначена для случаев, когда SQL нет. Вот вы от веб-сервиса получили сотню записей — вы будете запихивать их в базу, чтобы применить SQL?
Кроме того, что сравнение с SQL идейно некорректно (вы ещё с C++ сравните), оно неадекватно и по другой причине: в реальном коде гораздо больше шансы увидеть толстые ORMы, а не голый SQL. На ORMы все плюются, но пользуются. Здесь примерно та же история.
не учитывая хайлоад приложения
PHP и хайлоад в одном предложении — признак недальновидности.
0
Да, точно. Времени не было толком, что бы сделать все.
Вот с сортировками правильными (хотя может и тут ошибки есть):
Разница с предыдущим вариантом использования нативного — не велика.
Я почемуто уверен, что вложенность будет выше, соотвестно степень N будет возростать.
Для решения на нативном коде — потребуется больше времени, хотя есть такая мудрость — «Нету смысла подключать дополнительный пакет компонентов в 100500 строк, чтобы твой исходник уменьшился на 10 строк».
P.S. Я не осуждаю и не навязываю холивар. Я уважаю вашу работу. Я пытаюсь разобраться в этом — «использование дополнительных библиотек — это всегда жертвование ресурсов, и здесь важно знать, чем ты жертвуешь и в каком количестве»
Вот с сортировками правильными (хотя может и тут ошибки есть):
Разница с предыдущим вариантом использования нативного — не велика.
Мера О та же самая. Коэффициенты и константы, разумеется, отличаются.
Я почемуто уверен, что вложенность будет выше, соотвестно степень N будет возростать.
Для решения на нативном коде — потребуется больше времени, хотя есть такая мудрость — «Нету смысла подключать дополнительный пакет компонентов в 100500 строк, чтобы твой исходник уменьшился на 10 строк».
P.S. Я не осуждаю и не навязываю холивар. Я уважаю вашу работу. Я пытаюсь разобраться в этом — «использование дополнительных библиотек — это всегда жертвование ресурсов, и здесь важно знать, чем ты жертвуешь и в каком количестве»
0
Вот с сортировками правильными
Теперь сортировка по коду первого символа в нижнем регистре. о_О Почему не strcmp?
Ладно, не суть важно. Погонял у себя (правда без xhprof) — соотношение примерно то же, только раз в пять быстрее.
1. На строковых лямбдах можно сэкономить (эвал — он и в Африке эвал).
2. Погонял туда-сюда числа продуктов и категорий — соотношение скорости между голым PHP и YaLinqo сохраняется, так что остаюсь убеждённым про тот же порядок сложности.
3. Вызовы функций в PHP таки космически дорогие…
0
2. Погонял туда-сюда числа продуктов и категорий — соотношение скорости между голым PHP и YaLinqo сохраняется, так что остаюсь убеждённым про тот же порядок сложности.
Очень круто, когда есть график, когда по X — размер данных, по Y — время :) Особенно если на графике показано несколько реализаций решения.
0
PHP и хайлоад в одном предложении — признак недальновидности.
Тоже спорно. Это уже как стереотип — ПХП плохой, подходит только для бюджетных не больших проектов.
С правильным подходом и хорошей архитектурой приложения — мощный инструмент, с помощью которого вполне можно и хайлоад приложения разрабатывать.
Просто слово «хайлоад» — резиновое. Нужно более конкретно говорить :)
P.S. На пхп писать «говнокод» в разы легче и порог вхождения низкий, в отличии от других языков, по этому так и бывает, что когда видишь уже готовый проект — начинается паника :)
+4
Прошу прощения, промахнулся. Переместил комментарий в правильную ветку.
0
А что там за проблема с лямбдами? Давно уже стараюсь на PHP не писать, так что просто не в курсе. Строки с кодом выглядят не приятно.
0
Был предложен патч который позволял избавиться от «function () {… } » и использовать более короткую запись, но мейнтейнеры посчитали что это слишком сложно и потому не нужно (тоже самое было и с полноценными геттерами и сеттерами аналогами из C#, там вообще было две реализации предложено). Вообще иногда кажется что они специально развивают язык в том направлении чтобы им могли пользоваться абсолютные идиоты, кладя болт на реальные проблемы (я всё удивляюсь как генераторы пропихнули)…
+4
C# для меня сейчас вообще единственная причина того, что у меня win — основная ОС. Да, да, есть Mono, но VS+R# слишком уж сладкая парочка.
0
«сложным» не в контексте «разработчики не разберутся как это использовать» а сложно поддерживать. Вообще сложность состоит в убогом парсере, от которого уже который год хотят избавиться (этот же чувак ответственен за то что в PHP есть генераторы), но пока есть другие приоритеты видимо. Вот они управление памятью перепилили, глядишь и парсером займутся.
0
Т.е. если от убого парсера всё-таки избавятся можно надеяться и на нормальные лямбы и на геттеры? Хорошо бы…
0
сложность состоит в убогом парсере
Что касается парсера, то меня убивают «фичи»:
1. Ура! Теперь можно писать
(new Foo)->baz()
!2. Ура! Теперь можно писать
foo()['baz']
!В каждой новой версии одно и то же…
0
грусть
картинка не грузится: habrastorage.org/files/59f/10c/bc0/59f10cbc05744da396d4d2b8029dc30b.png
картинка не грузится: habrastorage.org/files/59f/10c/bc0/59f10cbc05744da396d4d2b8029dc30b.png
+1
Sign up to leave a comment.
YaLinqo (LINQ to Objects для PHP) — версия 2.0