Здравствуйте, Sinclair, Вы писали:
V>>Экспериментировал я с выходом linq.
S>Ну вот он и вышел в C# 3.0. Зачем иметь свои IOperation<Result>, когда есть Expression<Func<Result>>?
Потому что мои Op выполняются, считай, сразу, без стадии компиляции в CIL на моей стороне.
S>Вызываем на нём Compile(), и получаем полноценный бинарный код, ничуть не хуже, чем у AddIntOp.Execute().
Берём серверную сторону, сервак работает 24x7.
Серверная сторона не для красного словца — та задача изначально под серверную сторону потребовалась.
Compile каждый раз порождает новый код, который остаётся в памяти процесса и нет способа этот мусор собрать.
Перезагрузки доменов теперь тоже нет.
Сравни с моим подходом, где семантически одинаковые выражения представлены одинаковым типом, т.е. кол-во бинарного кода растёт лишь по мере роста разнообразия выражений.
Это примерно как в случае роста твоего B+ дерева.
Рост сложности выражений я ограничил на уровне 5 через боксирование, т.е. использование периодически чистых интерфейсов во время построения типа.
Хотя, и глубины 5 на практике достигалось редко.
V>>Специально не делал то замечание, что сейчас арифметические операторы можно делать в генериках.
V>>С тобой же не раз обсуждали способы решения этой задчи.
S>Это вообще ортогональная задача. Арифметические операторы в интерфейсах позволяют нам делать арифметические функции типа T Sum(IEnumerable<T> operands).
Через тип-словарик это можно было делать и раньше, но конкретно в этой задаче генерик-реализация экономила мало, бо в том "калькуляторе" использовалось два числовых типа всего — целочисленный long и double. Int — это я просто суть происходящего показывал на пальцах. И обслуживать те типы "раздельно" тоже было удобно, бо напрямую long и double не взаимодействуют в арифметических операциях, а только через предварительную промежуточную операцию приведения long к double, т.е. простой if в коде парсера-билдера оперирует не-генерик типами, а обычными, что тоже где-то удобно, в отсутствии протягиваемого для type-билдера лишней пары генерик-параметров (T и TOpProvider where TOpProvider : IOpProvider<T>).
V>>На пальцах: статические локальные ф-ии ввели относительно недавно.
V>>Походу, под эту новую фичу не успели доработать некий внутренний ExpressionBuilder.
S>Эмм, по-моему, кто-то отстаёт от дискуссии.
Да нет, это ты ответвился от сути моих замечаний.
Замечаний два, они взаимосвязаны:
— Expression вшит в C# и нет возможности подставить некий свой expression builder для ламбд;
— сам ExpressionBuilder обслуживает не все виды лямбд, хотя именно для их обслуживания создавался.
S>Некий внутренний ExpressionBuilder "не успели" доработать до примерно всего, что появилось после C# 3.0.
Разве?
Вот списочек:
https://docs.microsoft.com/ru-ru/dotnet/csharp/whats-new/csharp-8
S>Это выглядит не как "неуспевание", а как намеренное решение не копать в эту сторону.
А что там надо копать для использования объявленного в методе вложенного статического метода?
Чем этот статический метод отличается от обычного?
Насколько я знаю — только именем со специальными префиксами, что-то типа "SomeClass::SomeMethod<>InternalMethod".
Т.е., переименуй SomeClass::SomeMethod<>InternalMethod в SomeClass::SomeMethod_InternalMethod и всё работает.
S>При этом важно понимать, что "внутренняя целостность" сама по себе имеет исключительно академическую ценность.
Не, важно понимать, что вопросы планирования, раздачи приоритетов, оценки трудоёмкости тех или иных вещей — это одна из важнйших стадий в любой инженерной разработке.
Этот факап не фатален, конечно, просто показывает, что у дотнета, оказывается, нет няньки.
Т.е., опен-сорсная реализация не означала отказ от няньчанья, но, похоже, с дотнетом происходит именно это.
Например, гугл строго няньчится со своим Хромом, хотя проект и в опен-сорсе.
S>В реальных проектах решения принимаются исходя из практической, а не академической ценности.
В реальных коммерческих проектах всегда весы — трудоёмкость vs получаемые плюшки.
Т.е. задачи сортируются не только по степени их важности, но и по соотношению цена:качество.
Чем лучше это соотношение, тем больший балл прибавляется к приоритету задачи.
А здесь ситуация вдвойне забавной получилась, бо поддержка статических локальных методов в expression builder не стоит дороже написания нового кода, который сгенерирует и выдаст новую ошибку компиляции с новым номером при попытке использовать статические локальные методы в expressions.
S>Вот, скажем, неумение использовать в деревьях выражений статик локалы аффектит примерно 0 человек в мире.
Опять эта ущербность вопреки здравому смыслу...
Как-то странно тебя колбасит от полёта фантазии в далекий коммунизм, где всё по-уму и давно хорошо работает, до полной деградации, до отказа даже от малого.
Рассуждения в таком духе заведомо ущербны, почему ты сам этого не видишь?
Рассуждая похожим образом:
— отсутствие linq в дотнете аффектило примерно 0 человек в мире
— отсутствие дотнета аффектило примерно 0 человек в мире
— и т.д.
Посмотри в зеркало, плиз, на каждый именно твой пост запросто можно отвечать "это никому не нужно" и "ты всё-равно до этого не доживёшь", бо ты пишешь сюда именно такой материал, заведомо допускающий именно таких оценок.
S>И для тех, кто на это напоролся, есть простой рецепт: перенесите статик локал в простой приватный статик. Всё, вопрос закрыт.
А зачем это делать ручками, если комплятор и так переносит статик локал в простой приватный статик? (в отличие от нестатик локал)
Т.е. суть именно в этом — фича уже готова и работает, ничего даже делать не надо.
S>Альтернатива — давайте расширим библиотеку, расширим компилятор, допишем тесты.
Дописать тесты им пришлось в любом случае.
Тесты на правильное генерирование ошибок, хотя бы.
S>А, да, самое главное — ресурсы ограничены, поэтому чтобы сделать это, придётся не сделать что-то другое.
Я думаю, что там всё малость проще.
Вряд ли дотнетные разработчики действительно сошли с ума, скорее, они рассматривают дотнетное сообщество как сборище инфантильных детей.
Им заранее облом отвечать на вопросы из разряда "а почему статические локальные ф-ии в linq использовать можно, а нестатические нет?".
Вот и весь секрет.
S>Ну вот и не нашлось никакой фичи в бэклоге, которая была бы нужна меньше, чем эта. Увы.
Что лишний раз напоминает о том, что ты плохо разбираешься в мотивации других людей.
Отчасти это объясняет странные пробуксовки в обсуждении с тобой на ровном месте.
Среди активных участников наших баталий я выделяю двух коллег, у которых необъяснимый провал в деле формулирования задач.
Как вообще можно работать инженером с низким таким навыком?
(при том, что многие жестко оппонирующие мне умеют это великолепно, тот же НС, т.е. дело тут не в совпадении или нет взглядов).
V>>Как ты ставил эксперименты, никто так с Linq не работает.
S>Ну, "если вы хотите добиться успеха, вы должны быть готовы делать то, чего не хотят делать другие".
Это формула мотивации при полученной высокой оценки трудоёмкости/наукоёмкости некоей задачи.
К делу формулирования задач это перпендикулярно.
"Угадать" тут можно разве что случайно, когда собственный интерес совпадёт с фактическими потребностями.
Ведь именно тут инженерия отличается от исскуства, хотя обе работы творческие, созидательные.
S>Вот отсутствие в ExpressionTrees тупл-инициализаторов торчит прямо наружу, и это мешает потенциальным клиентам linq2d.
Разве?
Тебе можно вернуть твои же возражения — решается так-то и так-то.
Func<(int, int)> f = ()=>(42, 42);
Expression<Func<(int, int)>> f1 = ()=> ValueTuple.Create(42, 42);
Причём, сравнение ValueTuple появилось только в C# 7.3, т.е., проблема в том, что уже имеющийся Tuple — это класс, поэтому, сделали новый тип ValueTuple<> и сущность tuple literal.
Т.е. этой функциональности в Expression банально нет, её надо пилить.
Я же рассуждал о том, что уже есть, но не доступно.
V>>Рассуждая так, дешевле совсем ничего не делать.
S>Нет. Отсутствие некоторых фич приносит прямой или косвенный убыток. Или, наоборот, допиливание каких-то фич может принести пользу большому количеству людей.
S>Так и принимаются продуктовые решения — постоянно приходится чем-то жертвовать.
Как принимаются решения я уже показывал выше.
Решения принимаются в несколько этапов, происходящих итеративно: из формулирования целей и приоритетов, затем из анализа потенциальной трудоёмкости задач, соотнесения с располагаемыми ресурсами, goto на начало.
Т.е., процесс принятия решений итеративный и непрерывный, обновляемый в т.ч. по мере фактического достижения тех или иных целей, изменений в ресурсах, изменений в стоимости решения тех или иных задач и т.д.
Поэтому, твои рассуждения "вот это надо, а это не надо" я воспринимаю как отрыв от объективной реальности, сорри (впрочем, как и всегда с тобой).
У каждого "надо" есть цена, где в отсутствии рассмотрения цены рассуждения о надобности профанируются.