Re[180]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 10.07.16 21:47
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>>>Практические соображения и алгоритмическая выразительность это разные вещи. Алгоритмически все это можно было бы уложить в один небольшой метод.

EP>>Номинально да, на практике же имеем совсем не номинальный boilerplate.
НС>На практике такие задачи встречаются крайне редко.

У меня постоянно.
Тем не менее, разговор-то не про часто/нечасто.

НС>>>Далеко не только. Еще недавно она была нужна даже для таких базовых вещей как лямбды.

EP>>"Недавно" это уже лет шесть как назад.
НС>Меньше 5.

Они появились раньше релиза стандарта 2011 — в MSVS 2010 и GCC 4.5 (2010).
Кстати, какого года там в C# стандарт ISO/ECMA?

НС>>>И для плохонького аналога анонимных типов она понадобилась. Причем ее не хватило в итоге, и пришлось допиливать при помощи макросов препроцессора.

EP>>Каких конкретно макросов?
НС>http://rsdn.ru/forum/dotnet/6462036.1
Автор: Evgeny.Panasyuk
Дата: 05.06.16


Так в языке запросов это не используется, там не нужны анонимные типы. Все макросы что там есть используются исключительно для определения таблиц:
DEFINE_TABLE
(
    foo,
    (int, id)
    (int, code)
    (double, value)
    (int, number)
);
Это же можно заменить на внешнюю кодогенерацию, так как всё равно придётся как-то синхронизироваться со схемой данных. В Linq2DB также предлагается внешняя кодогенерация.

НС>>>Ты обсуждаешь простейший алгоритм на С++ с его конкретной реализацией для дотнета, содержащей кучу подробностей, связанных со спецификой платформы. Это самая натуральная демагогия.

EP>>На C++ из всей "специфики платформы" к этому алгоритму будет несколько десятков строк врапперов для Range интерфейсов
НС>И?

И то что в полной реализации C++ будет намного меньше чем то что есть в CodeJam. Это пример к исходному тезису.

НС>Понимаешь, никто тут не утверждает, в отличие от любителей С++, что С# круче всех и лишен каких либо недостатков.


А я разве утверждал что C++ круче всех? Я говорил про конкретный аспект, в котором он действительно лучше, но из этого не следует что "C++ круче всех"

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


К чему это? Я вполне замечаю недостатки и сразу признаю, и поэтому флеймов из этого не вырастает. Более того, без проблем использую C# когда требуется, и если нужна будет ещё и работа с БД — посмотрю на linq2db, и ЕМНИП я даже успел сказать это в текущем топике.

Километровый флейм тут (да и соседней теме) вырос от нежелания признать что простейший алгоритм вылился в несколько сот строк boilerplate, причём плохо поддерживаемых, ибо много копипасты + текстовая кодогенерация.
Аргументация же оппонентов постоянно витает где-то в далеких от исходного тезиса темах, типа экономической целесообразности, наличия мух в голове авторов кода, редкости таких ситуаций, метапрограммирования на макросах и шаблонах и т.п.
Re[180]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 10.07.16 21:59
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>>>>>А это для лучшего перформанса.

EP>>>>Так я и говорю, этот код пришлось написать из вполне конкретных практических соображений. Был бы язык/платформа/компилятор мощнее — его бы и не пришлось писать, о чем собственно и речь.
S>>>А то, что тебе приходится писать жуткие макросо-шаблоны в которых разбираешься только ты считаешь достоинством платформы?
EP>>Так это же для реализации языка запросов времени компиляции с нулевыми накладными расходами — в рамках непосредственно C# такое и вовсе нереализуемо
НС>А оно не особо то и нужно.

Так это же был ответ на выделенное. К обсуждению алгоритма min element он зачем-то притянул метапрограммирование в совершенно другом примере, который к тому же и не реализуем на C#.

НС>А оно не особо то и нужно. Компиляции при первом использовании вполне достаточно в 99.99% случаев.


Так я и не спорю, возможно и не стоит. Уже выше писал:

EP>>>Такие запросы тоже можно сгенерировать во время компиляции — вопрос в количестве вариантов.
IT>>В этом нет смысла. Единственная проблема ET — это сложность получения хешь функции самого дерева, т.к. оно перестраивается компилятором при каждом вызове. Если делать свой собственный DSL, то такую возможность можно предусмотреть и тогда проблема кеширования запросов отпадает. Т.е. не стоит выпрыгивать из штанов в compile-time, получая неполноценный результат.
EP>Не спорю, возможно и не стоит.
EP>Я лишь говорю о том, что многие преимущества linq, в том числе и то что ты называешь главным козырем — type-safety, можно получить через генерацию compile-time, даже для динамических запросов. Насколько же это целесообразно — отдельный и важный вопрос.

Re[182]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 10.07.16 22:06
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>>>> А то, что тебе приходится писать жуткие макросо-шаблоны в которых разбираешься только ты считаешь достоинством платформы?

EP>>>>Так это же для реализации языка запросов времени компиляции с нулевыми накладными расходами — в рамках непосредственно C# такое и вовсе нереализуемо
S>>> Да можно, только это никому не нужно. Разберись в предметной области.
S>>>...
EP>>
S> Молодец, то что ниже опускаешь. И игнорируешь.

Каков хитрец, отредактировал сообщение и теперь говоришь что я игнорирую добавленную часть

S>

S> Но вполне возможно, что будет жесткая привязка к провайдеру в EF7 .Net Native.
S> Если можно динамически скомпилировать, то что мешает это сделать при компиляцмм программмы?

S> То есть твое утверждение, что " в рамках непосредственно C# такое и вовсе нереализуемо "
S>Это ложь. Это не реализуемо в рамках конкретной реализации EF. Но никак не языка.

Так я же говорю про "непосредственно C#", а не какие-либо внешние утилиты.
Re[181]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 10.07.16 22:07
Оценка: :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Километровый флейм тут (да и соседней теме) вырос от нежелания признать что простейший алгоритм вылился в несколько сот строк boilerplate, причём плохо поддерживаемых, ибо много копипасты + текстовая кодогенерация.

EP>Аргументация же оппонентов постоянно витает где-то в далеких от исходного тезиса темах, типа экономической целесообразности, наличия мух в голове авторов кода, редкости таких ситуаций, метапрограммирования на макросах и шаблонах и т.п.
Еще раз. Тебе я привел кучу примеров. Приведу еще один

//if (value == null)
 //    source=source.Where(x=>x!=null); // Уберем фильтр на Linq из-за тормоза делегата

                bool isFirst=true;
                bool fl=0;
                foreach(var item in source)
                {
                   // Поставим фильтр сюда
                  if (isNullable && item == null) continue;

                   var x = selector(item ); 
                   if (isFirst) 
                      {                  
                      isFirst=false;
                       fl=-1;
                     }
                    else
                      fl=comparer.Compare(x,value);
                                 
                        if (fl< 0)
                        {
                            value = x;
                            result= item;
                        }
                    }
                
                                  if (isFirst)
                  
                                  { 
                                    // по их алгоритму при пустом списке вызвать исключение для Nullable
                                      if (isNullable)
                                        throw NoElementsException();
                                          else
                                       return default(TSource); // вернуть default при пустом списке 
                                    }
            return result;


Получим тот же перфоманс без копи-пасте.
Приводи свой алгоритм на C++ который в 100 раз меньше.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 15.07.2016 14:57 Serginio1 . Предыдущая версия . Еще …
Отредактировано 15.07.2016 14:56 Serginio1 . Предыдущая версия .
Отредактировано 15.07.2016 14:55 Serginio1 . Предыдущая версия .
Отредактировано 15.07.2016 14:45 Serginio1 . Предыдущая версия .
Re[181]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Ночной Смотрящий Россия  
Дата: 10.07.16 22:12
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>У меня постоянно.


Значит .NET тебе плохо подходит.

EP>Так в языке запросов это не используется


При чем тут язык запросов?

EP>, там не нужны анонимные типы. Все макросы что там есть используются исключительно для определения таблиц:


Суть ad-hoc типов в том и состоит, что сам запрос операцией проекции порождает новую "таблицу". Я ж ведь не зря говорил про простейший случай. Как вместо простой ссылки на поле таблицы нарисовалось выражение — уже какой то NEW вылез. А если после операции проекции нам надо опять фильтр наложить? Сгруппировать? Еще одну проекцию добавить? Сделать union двух разных по происхождению но с совпадающим типом проекций?

EP>
EP>DEFINE_TABLE
EP>(
EP>    foo,
EP>    (int, id)
EP>    (int, code)
EP>    (double, value)
EP>    (int, number)
EP>);
EP>
Это же можно заменить на внешнюю кодогенерацию, так как всё равно придётся как-то синхронизироваться со схемой данных.


А руками если написать, во что это превратится?

EP>И то что в полной реализации C++ будет намного меньше чем то что есть в CodeJam.


Если это будет С++ для safe дотнета, то не особо меньше. А сравнивать алгоритмы с разными нефункциональными требованиями, причем сравнивать именно эти самые нефункциональные требования — чистейшая демагогия.

НС>>Понимаешь, никто тут не утверждает, в отличие от любителей С++, что С# круче всех и лишен каких либо недостатков.

EP>А я разве утверждал что C++ круче всех?

А разве ты тут писал про то, что С++ в чем то хуже С#? Хотя бы пару раз?

EP> Я говорил про конкретный аспект, в котором он действительно лучше


Да нет. Конкретный аспект называется дженерик-арифметика, а ты обобщил на всю алгоритмическую выразительность. Если бы ты сказал, что дженерик арифметику на С++ писать намного проще — тебе бы и слова никто не сказал.

EP>К чему это? Я вполне замечаю недостатки и сразу признаю


Ссылочки можно?

EP>Аргументация же оппонентов постоянно витает где-то в далеких от исходного тезиса темах, типа экономической целесообразности, наличия мух в голове авторов кода, редкости таких ситуаций, метапрограммирования на макросах и шаблонах и т.п.


А на самом деле все с точностью до наоборот. Оппоненты говорят о вполне конкретных моментах в реальном коде и конкретном опыте работы, а ты в ответ пичкаешь их полутеоретическими изысканиями в вопросах, в которых опыта у тебя около нуля. Та еще ржака смотреть, как ты с алексом рассказываете про то как надо правильно работать с БД Синклеру и ИТ.
Re[181]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Ночной Смотрящий Россия  
Дата: 10.07.16 22:18
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>Не спорю, возможно и не стоит.

EP>>Я лишь говорю о том, что многие преимущества linq, в том числе и то что ты называешь главным козырем — type-safety, можно получить через генерацию compile-time

Так нельзя же! Потому что запросы динамические часто (или даже почти всегда, я и ИТ примеры таких ситуаций приводили), статически их нельзя создать в принципе. При этом вся type safety в линке сохраняется в полный рост, включая, при необходимости, даже проверки в рантайме, а вот ваши стрококлеи остаются при этом не у дел, в лучшем случае обработав совсем примитивные варианты с риском получить комбинаторный взрыв.
Понимаешь, твоих оппонентов не интересует возможность теоретически получить какой то результат в некоторых ситуациях. Им интересен реальный рабочий инструмент. И linq2db таковым является в полный рост, а вот sqlpp — увы и ах.
Re[183]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 10.07.16 22:19
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:


S>> То есть твое утверждение, что " в рамках непосредственно C# такое и вовсе нереализуемо "

S>>Это ложь. Это не реализуемо в рамках конкретной реализации EF. Но никак не языка.

EP>Так я же говорю про "непосредственно C#", а не какие-либо внешние утилиты.

То есть например если это будет сделано в компиляторе .Net Native это внешняя утилита?
Она кстати использует Компилятор С++
https://rsdn.ru/forum/flame.comp/6497386.1
Автор: Serginio1
Дата: 10.07.16


.NET Native использует то же сервер, что и компилятор C++, который оптимизирован для статических сценариев предварительной компиляции.


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

При работе с провайдером ему подается ET которое он может скомпилировать и закэшировать.
То, что можно в динамике, можно сделать и в статике со статическим ET.

С заранее известному провайдеру можно пойти двумя способами.
1. Трансформация IL кода. Разобрав существующий IL код и встретив IQueryable, можно получить статическое ET скормить его провайдеру и получить IL код и заменить его.
2. Например можно создать для .Net Native расширения которые будут сразу компилировать.
Здесь проблема не в языке, а в компиляторе.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 11.07.2016 6:47 Serginio1 . Предыдущая версия .
Re[182]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 10.07.16 23:03
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>У меня постоянно.

НС>Значит .NET тебе плохо подходит.

Не подходит к моим текущим задачам.

EP>>Так в языке запросов это не используется

НС>При чем тут язык запросов?

При том что в моём примере на генерацию запроса и т.п. во время компиляции этого макроса нет.

EP>>, там не нужны анонимные типы. Все макросы что там есть используются исключительно для определения таблиц:

НС>Суть ad-hoc типов в том и состоит,

Я не знаю что ты называешь ad-hoc типами. Я даже отдельную тему с вопросом создал.
Либо конкретно C# Anonymous Type, либо синтезирование нового типа по месту (ad-hoc) что не означает только Anonymous Type.
Пример с макросом NEW был именно на Anonymous Type, и в другой теме. Синтезирование же типов по месту реализуется в том числе и другими механизмами.

НС>что сам запрос операцией проекции порождает новую "таблицу". Я ж ведь не зря говорил про простейший случай. Как вместо простой ссылки на поле таблицы нарисовалось выражение — уже какой то NEW вылез.


Нет в моём примере никакого макроса NEW, он был в другой теме. Вот пример использования:
from(foo).where(foo.id > 42_i).select(foo.value, foo.id, foo.number)
Здесь нет ни одного макроса.

НС>А если после операции проекции нам надо опять фильтр наложить? Сгруппировать? Еще одну проекцию добавить?


Без проблем, вот мой текущий вариант.
auto q = from(foo).where(foo.id > 42_i).select(foo.value, foo.id).select(foo.number);

for(auto &x : to_vector( q ))
    cout << "ROW: " << x.id << " " << x.value << " " << x.number << endl;

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

НС>Сделать union двух разных по происхождению но с совпадающим типом проекций?


Не вижу проблемы, особенно если типы совпадают.

EP>>
EP>>DEFINE_TABLE
EP>>(
EP>>    foo,
EP>>    (int, id)
EP>>    (int, code)
EP>>    (double, value)
EP>>    (int, number)
EP>>);
EP>>
Это же можно заменить на внешнюю кодогенерацию, так как всё равно придётся как-то синхронизироваться со схемой данных.

НС>А руками если написать, во что это превратится?

Вот отформатированный вывод препроцессора:
  Скрытый текст
struct foo_aux
{
    using table_type = foo_aux;
    struct id_column
    {
        struct field_id
        {
            struct name_string
            {
                static constexpr auto value() { return "id"; }
            };
            template <typename T>
            struct field
            {
                T id;
            };
            template <typename T>
            static auto &access(T &x)
            {
                return x.id;
            }
        };
        using type = CTQL::table_column<table_type, int, field_id>;
    };
    struct code_column
    {
        struct field_code
        {
            struct name_string
            {
                static constexpr auto value() { return "code"; }
            };
            template <typename T>
            struct field
            {
                T code;
            };
            template <typename T>
            static auto &access(T &x)
            {
                return x.code;
            }
        };
        using type = CTQL::table_column<table_type, int, field_code>;
    };
    struct value_column
    {
        struct field_value
        {
            struct name_string
            {
                static constexpr auto value() { return "value"; }
            };
            template <typename T>
            struct field
            {
                T value;
            };
            template <typename T>
            static auto &access(T &x)
            {
                return x.value;
            }
        };
        using type = CTQL::table_column<table_type, double, field_value>;
    };
    struct number_column
    {
        struct field_number
        {
            struct name_string
            {
                static constexpr auto value() { return "number"; }
            };
            template <typename T>
            struct field
            {
                T number;
            };
            template <typename T>
            static auto &access(T &x)
            {
                return x.number;
            }
        };
        using type = CTQL::table_column<table_type, int, field_number>;
    };

    struct name_string
    {
        static constexpr auto value() { return "foo"; }
    };

    using type = CTQL::make_table<name_string, id_column, code_column, value_column, number_column>;
};
foo_aux::type foo;


EP>>И то что в полной реализации C++ будет намного меньше чем то что есть в CodeJam.

НС>Если это будет С++ для safe дотнета, то не особо меньше. А сравнивать алгоритмы с разными нефункциональными требованиями, причем сравнивать именно эти самые нефункциональные требования — чистейшая демагогия.

Есть задача написать алгоритм, естественно нормальным способом, а не номинальным или абы-каким. И вот в CodeJam руководствуясь вполне практическими целями и написали.
А рассуждения о нефункциональности требований и т.п. это всё лирика. Есть реальный код, и его много.

НС>>>Понимаешь, никто тут не утверждает, в отличие от любителей С++, что С# круче всех и лишен каких либо недостатков.

EP>>А я разве утверждал что C++ круче всех?
НС>А разве ты тут писал про то, что С++ в чем то хуже С#? Хотя бы пару раз?

Из текущего топика:

EP>>>>>Лямбды лаконичнее — да, реализация алгоритма — нет.
S>>>> Если ты про замыкания, то там строится класс компилятором.
EP>>>Я про синтаксис использования лямбд.
S>> По мне так все сообразно функциональным языкам. Автоматический вывод типа.
EP>И? Ты вообще не понимаешь о чём идёт речь? Я говорю что синтаксис лямбд лаконичней в C# — нет лишних скобок, return и auto.


EP>> Я говорил про конкретный аспект, в котором он действительно лучше

НС>Да нет. Конкретный аспект называется дженерик-арифметика, а ты обобщил на всю алгоритмическую выразительность. Если бы ты сказал, что дженерик арифметику на С++ писать намного проще — тебе бы и слова никто не сказал.

Что такое "дженерик-арифметика", конкретно?

EP>>К чему это? Я вполне замечаю недостатки и сразу признаю

НС>Ссылочки можно?

Выше было про лямбды. Сейчас искать лень, если ещё найду — то скину.

НС>Та еще ржака смотреть, как ты с алексом рассказываете про то как надо правильно работать с БД Синклеру и ИТ.


А где я вообще сказал что я показываю как надо правильно работать с БД?
Я утверждаю что язык запросов времени компиляции с минимальным или нулевым overhead'ом вполне реализуем (причём необязательно на C++, это может быть и например D/Rust/Nemerle). ВСЁ — это мой главный тезис во всей этой ветке.
Кто-то выше утверждает что это невозможно — я в ответ привожу конкретные примеры.
При этом не давал оценки реальной практической необходимости именно такого варианта.
Re[182]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 10.07.16 23:33
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>>Не спорю, возможно и не стоит.

EP>>>Я лишь говорю о том, что многие преимущества linq, в том числе и то что ты называешь главным козырем — type-safety, можно получить через генерацию compile-time
НС>Так нельзя же!

Для статических и некоторых динамических — можно. Для остальных есть шанс получить меньший overhead.

НС>Потому что запросы динамические часто


Кстати, а что имелось в виду здесь:

http://rsdn.ru/forum/flame.comp/6453427.1


Нет, это у тебя проблемы со знанием предметной области. По моему опыту, в типичном ERP приложении примерно 90% запросов не содержат динамических ветвлений. Так что 1000 запросов это вообще ни о чем.

http://rsdn.ru/forum/flame.comp/6452046.1
Автор: Ночной Смотрящий
Дата: 24.05.16

_>>Приложение с 1000 разных статических запросов к СУБД? ) Это было бы любопытно взглянуть на подобного эпичного монстра... )))
НС>1000 запросов это эпичный монстр?

?

НС>Понимаешь, твоих оппонентов не интересует возможность теоретически получить какой то результат в некоторых ситуациях.


За всех не говори.
Например они делают заявления о теоретической возможности/невозможности чего-то, с этим я и спорю. Например:

G>>Это api для более-менее типизированного построения примитивных запросов. Он не может никаким образом получить два разных запроса из одного и того же куска кода. Даже теоретически.
EP>Это ещё почему? Например у него есть коннектор в БД, и к обычным контейнерам — один и тот же запрос может выполнять совершенно разные веши

EP>>>>Тип в который в том числе закодировано дерево выражения. На C++ это реализуется с помощью техники Expression Templates, которой уже более двадцати лет.
G>>>Показывай минимально работающий пример, который обходит дерево и строит SQL.
EP>>Показывающий что конкретно? Проекции? Фильтры? Автоматические join'ы по связям?
G>Фильтры и проекции, с джоинами потом разберемся
EP>>Это всё ни одна сотня строк кода, реализовать которые мне не интересно.
G>Тогда какой смысл в том, что ты пишешь? На практике никто такое не сделал, значит невозможно. Иначе уже была бы реализован аналог linq на C++.

Или например спрашивают про реализацию:

G>1) Так ты покажи макрос conditional или что там у тебя. А то так можно любой код написать и объявить его "статическим".
G>2) Как делать декомпозицию \ композицию таких запросов? В идеале так:http://blog.gandjustas.ru/2010/05/30/iqueryable-generics/

EP>>Так и в случае с compile-time EDSL такое возможно
I>Теоретически возможно, но пока ничего работающего ни ты, ни alex_public не показали.


НС>Им интересен реальный рабочий инструмент. И linq2db таковым является в полный рост, а вот sqlpp — увы и ах.


Так я и не агитирую за sqlpp11, там вполне может чего-то не быть, что никак не является опровержением моих слов.
Re[183]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Ночной Смотрящий Россия  
Дата: 11.07.16 07:27
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Я не знаю что ты называешь ad-hoc типами. Я даже отдельную тему с вопросом создал.


Тебе там вроде доходчиво ответили.

EP>Пример с макросом NEW был именно на Anonymous Type, и в другой теме.


Анонимные типы это реализация ad-hoc типов в C#, что непонятно то?

EP> Синтезирование же типов по месту реализуется в том числе и другими механизмами.


Чем, в твоем понимании, отличается "синтезирование тпов по месту" и анонимный тип с выражениями?

НС>>что сам запрос операцией проекции порождает новую "таблицу". Я ж ведь не зря говорил про простейший случай. Как вместо простой ссылки на поле таблицы нарисовалось выражение — уже какой то NEW вылез.


EP>Нет в моём примере никакого макроса NEW, он был в другой теме.


Он есть прямо по той ссылке, что ты сам сюда и притащил.

EP> Вот пример использования:


Опять самый примитивный. О чем и речь.

НС>>А если после операции проекции нам надо опять фильтр наложить? Сгруппировать? Еще одну проекцию добавить?


EP>auto q = from(foo).where(foo.id > 42_i).select(foo.value, foo.id).select(foo.number);


И это все богатство превратится в SQL полностью?

EP>Вот отформатированный вывод препроцессора:


Отож. А теперь посмотри на то, что генерирует шаблон linq2db — там обычные объекты, а не страшное чудовище. Суть этой генерации не в том чтобы нагенерить кучу говнокода, а в том чтобы генерить это из структуры БД.

НС>>Если это будет С++ для safe дотнета, то не особо меньше. А сравнивать алгоритмы с разными нефункциональными требованиями, причем сравнивать именно эти самые нефункциональные требования — чистейшая демагогия.

EP>Есть задача написать алгоритм

Нет, задача в случае CodeJam шире. Нефункциональные требования, слышишь?

EP>А рассуждения о нефункциональности требований и т.п. это всё лирика.


А, ну ну.

НС>>А разве ты тут писал про то, что С++ в чем то хуже С#? Хотя бы пару раз?

EP>Из текущего топика:

Ага, лямбды конечно лаконичнее, но С++ все равно лучше. ЧТД.

EP>Что такое "дженерик-арифметика", конкретно?


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

НС>>Та еще ржака смотреть, как ты с алексом рассказываете про то как надо правильно работать с БД Синклеру и ИТ.

EP>А где я вообще сказал что я показываю как надо правильно работать с БД?

Весь этот топик вы тут убеждаете, что линк это гавно и неправильный подход.

EP>Я утверждаю что язык запросов времени компиляции с минимальным или нулевым overhead'ом вполне реализуем


Для частных случаев.

EP>Кто-то выше утверждает что это невозможно


Невозможно? Или непрактично?

EP>При этом не давал оценки реальной практической необходимости именно такого варианта.


А тебе постоянно указывают именно на непрактичность.
Re[183]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Ночной Смотрящий Россия  
Дата: 11.07.16 07:32
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

НС>>Так нельзя же!

EP>Для статических и некоторых динамических — можно.

Т.е. в общем случае нельзя.

НС>>Потому что запросы динамические часто


EP>http://rsdn.ru/forum/flame.comp/6453427.1
Автор: Ночной Смотрящий
Дата: 25.05.16

EP>Нет, это у тебя проблемы со знанием предметной области. По моему опыту, в типичном ERP приложении примерно 90% запросов не содержат динамических ветвлений. Так что 1000 запросов это вообще ни о чем.

Те запросы, которые непосредственно пишут прикладники — те динамические в 10, может в 20% случаев. Но вот финальный запрос может быть динамическим в 100%. Понятно?

НС>>Понимаешь, твоих оппонентов не интересует возможность теоретически получить какой то результат в некоторых ситуациях.

EP>За всех не говори.
EP>Например они делают заявления о теоретической возможности/невозможности чего-то, с этим я и спорю. Например:
...
I>>Теоретически возможно, но пока ничего работающего ни ты, ни alex_public не показали.

Re[184]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 12.07.16 09:31
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>Я не знаю что ты называешь ad-hoc типами. Я даже отдельную тему с вопросом создал.

НС>Тебе там вроде доходчиво ответили.

Это их предположение, интерпретация, откуда мне знать совпадает ли она с твоей.
Вообще говоря anonymous не является синонимом ad-hoc — это какая-то отсебятина. Ad-hoc может быть совсем не анонимным.

EP>> Синтезирование же типов по месту реализуется в том числе и другими механизмами.

НС>Чем, в твоем понимании, отличается "синтезирование тпов по месту" и анонимный тип с выражениями?

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

НС>>>что сам запрос операцией проекции порождает новую "таблицу". Я ж ведь не зря говорил про простейший случай. Как вместо простой ссылки на поле таблицы нарисовалось выражение — уже какой то NEW вылез.

EP>>Нет в моём примере никакого макроса NEW, он был в другой теме.
НС>Он есть прямо по той ссылке, что ты сам сюда и притащил.

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

EP>> Вот пример использования:

НС>Опять самый примитивный. О чем и речь.

А какой нужен? Более сложные варианты тоже возможны, и например есть в примерах sqlpp11.

НС>>>А если после операции проекции нам надо опять фильтр наложить? Сгруппировать? Еще одну проекцию добавить?

EP>>auto q = from(foo).where(foo.id > 42_i).select(foo.value, foo.id).select(foo.number);
НС>И это все богатство превратится в SQL полностью?

В первой же строчке вывода примера показан SQL:
SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42


EP>>Вот отформатированный вывод препроцессора:

НС>Отож. А теперь посмотри на то, что генерирует шаблон linq2db — там обычные объекты, а не страшное чудовище.

В linq2db также и вспомогательный код

НС>Суть этой генерации не в том чтобы нагенерить кучу говнокода, а в том чтобы генерить это из структуры БД.


И там и там цель связать пользовательский код с БД. А сколько там строчек в текстовом шаблоне у кодогенератора — вообще не принципиально

НС>>>Если это будет С++ для safe дотнета, то не особо меньше. А сравнивать алгоритмы с разными нефункциональными требованиями, причем сравнивать именно эти самые нефункциональные требования — чистейшая демагогия.

EP>>Есть задача написать алгоритм
НС>Нет, задача в случае CodeJam шире. Нефункциональные требования, слышишь?

Конечно, не надо обрезать цитату:

EP>>Есть задача написать алгоритм, естественно нормальным способом, а не номинальным или абы-каким.


НС>>>А разве ты тут писал про то, что С++ в чем то хуже С#? Хотя бы пару раз?

EP>>Из текущего топика:
НС>Ага, лямбды конечно лаконичнее, но С++ все равно лучше. ЧТД.

У тебя с логикой проблемы? Где я это говорил? Мои слова:

Лямбды лаконичнее — да, реализация алгоритма — нет.

ВСЁ. Свои додумки оставляй при себе.

EP>>Что такое "дженерик-арифметика", конкретно?

НС>Использование арифметических и логических операторов в дженерик коде.
НС>Дженерики, в отличие от плюсовых шаблонов, компилируются в бинарник именно в виде шаблонов. Поэтому вот так просто взять и использовать в нем операторы нельзя.

Это звучит как очередная кривость языка/платформы, а не как принципиальное ограничение компиляции в бинарник как шаблона.
Чем операторы отличаются от других методов/функций?

НС>>>Та еще ржака смотреть, как ты с алексом рассказываете про то как надо правильно работать с БД Синклеру и ИТ.

EP>>А где я вообще сказал что я показываю как надо правильно работать с БД?
НС>Весь этот топик вы тут убеждаете, что линк это гавно и неправильный подход.

Опять ты врёшь. Где я это утверждаю?

EP>>Кто-то выше утверждает что это невозможно

НС>Невозможно? Или непрактично?

"Невозможно" в том числе, и в том числе "теоретически".
Re[184]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 12.07.16 09:38
Оценка: -1
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>>>Понимаешь, твоих оппонентов не интересует возможность теоретически получить какой то результат в некоторых ситуациях.

EP>>За всех не говори.
EP>>Например они делают заявления о теоретической возможности/невозможности чего-то, с этим я и спорю. Например:
НС>...
I>>>Теоретически возможно, но пока ничего работающего ни ты, ни alex_public не показали.
НС>

О, уже художественная резка по цитатам началась
Учу читать:


НС>>Понимаешь, твоих оппонентов не интересует возможность теоретически получить какой то результат в некоторых ситуациях.

EP>За всех не говори.
EP>

Например они делают заявления о теоретической возможности/невозможности чего-то, с этим я и спорю. Например:

EP>

G>>>Это api для более-менее типизированного построения примитивных запросов. Он не может никаким образом получить два разных запроса из одного и того же куска кода. Даже теоретически.
EP>>Это ещё почему? Например у него есть коннектор в БД, и к обычным контейнерам — один и тот же запрос может выполнять совершенно разные веши

EP>

EP>>>>>Тип в который в том числе закодировано дерево выражения. На C++ это реализуется с помощью техники Expression Templates, которой уже более двадцати лет.
G>>>>Показывай минимально работающий пример, который обходит дерево и строит SQL.
EP>>>Показывающий что конкретно? Проекции? Фильтры? Автоматические join'ы по связям?
G>>Фильтры и проекции, с джоинами потом разберемся
EP>>>Это всё ни одна сотня строк кода, реализовать которые мне не интересно.
G>>Тогда какой смысл в том, что ты пишешь? На практике никто такое не сделал, значит невозможно. Иначе уже была бы реализован аналог linq на C++.

Или например спрашивают про реализацию:

EP>

G>>1) Так ты покажи макрос conditional или что там у тебя. А то так можно любой код написать и объявить его "статическим".
G>>2) Как делать декомпозицию \ композицию таких запросов? В идеале так:http://blog.gandjustas.ru/2010/05/30/iqueryable-generics/

EP>

EP>>>Так и в случае с compile-time EDSL такое возможно
I>>Теоретически возможно, но пока ничего работающего ни ты, ни alex_public не показали.

Re[120]: Тормознутость и кривость linq
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.07.16 10:48
Оценка:
Здравствуйте, gandjustas, Вы писали:
G>Но я говорил не про кеш таблиц, а про кеш результатов запроса. Его почти нигде нет или тупо не используется, потому что нереально обеспечить его когерентность.
Я лет 15 назад читал про semantic caching, где между клиентом и сервером вклинивалась in-memory RDBMS, способная отвечать на запросы из кэша. Там прямо была продвинутая техника анализа, которая позволяла второй запрос выполнить без обращения на сервер:
select * from students where lastName = 'Smith';
select * from students where lastName = 'Smith' and age = 21;

При этом аналогичная логика трассировала предикаты в insert, update и delete, чтобы обсолетить результаты.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[129]: Тормознутость и кривость linq
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.07.16 11:05
Оценка:
Здравствуйте, alex_public, Вы писали:

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

Да мы там даже код прошивки от Apollo 11 видели.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[185]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Ночной Смотрящий Россия  
Дата: 12.07.16 11:30
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Вообще говоря anonymous не является синонимом ad-hoc


anonymous — реализация ad-hoc в конкретном языке.

EP>Ad-hoc может быть совсем не анонимным.


Смысла в неанонимности ad-hoc нет.

НС>>Чем, в твоем понимании, отличается "синтезирование тпов по месту" и анонимный тип с выражениями?

EP>Тем что синтезируется именно анонимный тип, причём с вполне конкретной спецификой. При этом в общем случае по месту может синтезироваться какой угодно тип.

Ничего не понял.

EP>>>Нет в моём примере никакого макроса NEW, он был в другой теме.

НС>>Он есть прямо по той ссылке, что ты сам сюда и притащил.
EP>Ну и что что он был по ссылке в каком одном из моих сообщений?

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

EP>>>auto q = from(foo).where(foo.id > 42_i).select(foo.value, foo.id).select(foo.number);

НС>>И это все богатство превратится в SQL полностью?
EP>В первой же строчке вывода примера показан SQL:
EP>
EP>SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42 
EP>


Это fail, потому что должно быть SELECT foo.number FROM ....

НС>>Отож. А теперь посмотри на то, что генерирует шаблон linq2db — там обычные объекты, а не страшное чудовище.

EP>В linq2db также и вспомогательный код

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

НС>>Суть этой генерации не в том чтобы нагенерить кучу говнокода, а в том чтобы генерить это из структуры БД.

EP>И там и там цель связать пользовательский код с БД.

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

НС>>Ага, лямбды конечно лаконичнее, но С++ все равно лучше. ЧТД.

EP>У тебя с логикой проблемы? Где я это говорил? Мои слова:
EP>

EP>Лямбды лаконичнее — да, реализация алгоритма — нет.

ВСЁ. Свои додумки оставляй при себе.


Никаких додумок. В этой цитате С++ у тебя опять лучше всех. А я тебя просил привести пример обратного. Ты не смог. ЧТД.

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

EP>Это звучит как очередная кривость языка/платформы

Это не просто звучит, это кривость и есть.

EP>Чем операторы отличаются от других методов/функций?


Тем что операторы не являются частью бинарного контракта экземпляра.
Re[186]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 12.07.16 14:49
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>>>Нет в моём примере никакого макроса NEW, он был в другой теме.

НС>>>Он есть прямо по той ссылке, что ты сам сюда и притащил.
EP>>Ну и что что он был по ссылке в каком одном из моих сообщений?
НС>По ссылке было вполне конкретное сообщение,

По ссылке был лишь пример того, что я знаю что такое Anonymous Type. Зачем ты на него ссылаешься, учитывая то что я неоднократно приводил полный код примера в этой теме, где ничего подобного нет.

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


Нет, там я этого не демонстрирую. Это очередной логический fail

EP>>>>auto q = from(foo).where(foo.id > 42_i).select(foo.value, foo.id).select(foo.number);

НС>>>И это все богатство превратится в SQL полностью?
EP>>В первой же строчке вывода примера показан SQL:
EP>>
EP>>SELECT foo.value, foo.id, foo.number FROM foo WHERE foo.id>42 
EP>>

НС>Это fail, потому что должно быть SELECT foo.number FROM ....

Учу читать:

EP>Тут второй select добавляет колонку в проекцию, это конечно не совсем верно, но для демонстрации изменения проекции вполне подойдёт.

Переделать поведение на SELECT foo.number FROM ... не проблема

НС>>>Отож. А теперь посмотри на то, что генерирует шаблон linq2db — там обычные объекты, а не страшное чудовище.

EP>>В linq2db также и вспомогательный код
НС>Опять не распарсил. Нет там никакого вспомогательного кода кроме необязательной разметки атрибутами. Обычные POCO.

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

НС>>>Ага, лямбды конечно лаконичнее, но С++ все равно лучше. ЧТД.

EP>>У тебя с логикой проблемы? Где я это говорил? Мои слова:
EP>>

EP>>Лямбды лаконичнее — да, реализация алгоритма — нет.

ВСЁ. Свои додумки оставляй при себе.

НС>Никаких додумок. В этой цитате С++ у тебя опять лучше всех.

Почему?

НС>А я тебя просил привести пример обратного. Ты не смог. ЧТД.


Мне может покаяться нужно что я привёл пример zero overhead? Или то что указал на ненормальность ситуации такого количества boilerplate для простейшего алгоритма?
А то уже какие-то странные разговоры пошли, мол лямбдами как-то не так восхитился, с чем связан восторг и т.п.
Re[187]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Ночной Смотрящий Россия  
Дата: 12.07.16 14:59
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>По ссылке был лишь пример того, что я знаю что такое Anonymous Type.


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

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

EP>Нет, там я этого не демонстрирую.

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

EP>Переделать поведение на SELECT foo.number FROM ... не проблема


Уверен?

НС>>Опять не распарсил. Нет там никакого вспомогательного кода кроме необязательной разметки атрибутами. Обычные POCO.

EP>Смотри внимательней, я тебе дал прямую ссылку на сгенерированный код, там есть и исполняемый код.

Где? Давай конкретно.

НС>>Никаких додумок. В этой цитате С++ у тебя опять лучше всех.

EP>Почему?

Потому что там написано, что хоть у C# ситаксис лямбд и лаконичнее, но в целом С++ лучше. Классика жанра — любой аргумент дезавуировать "но в главном то он прав".

НС>>А я тебя просил привести пример обратного. Ты не смог. ЧТД.

EP>Мне может покаяться нужно что я привёл пример zero overhead?

Не надо тебе каятся, просто надо признать что все что ты тут пишешь предельно однобоко. Надо быть слепым чтобы этого не замечать.
Re[188]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Evgeny.Panasyuk Россия  
Дата: 12.07.16 15:59
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>По ссылке был лишь пример того, что я знаю что такое Anonymous Type.

НС>Нет, там был ответ на вопрос — как будут выглядеть твои типы в случае, когда там выражение, а не просто поле.

Так а вопрос был по-твоему в ответ на что?

EP>>Что такое анонимные типы в C# я знаю, даже реализовывал

аналог на C++.
AVK>И что, там можно давать полям новые имена и использовать сложные выражения? Потому что примитивные варианты в примерах по ссылке это интересно, но практически не особо полезно. А примеров посложнее там нет.


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

EP>>Нет, там я этого не демонстрирую.
НС>Ничего не понял. Тебе задали конкретный вопрос — что будет, если там выражение. Ты привел решение с макросами.

Вопрос задали про тот конкретный пример.

EP>>Переделать поведение на SELECT foo.number FROM ... не проблема

НС>Уверен?

Заменяем
return query<Table, Condition, Columns..., RightColumns...>{};
на
return query<Table, Condition, RightColumns...>{};

И получаем запрос
SELECT foo.number FROM foo WHERE foo.id>42


НС>>>Опять не распарсил. Нет там никакого вспомогательного кода кроме необязательной разметки атрибутами. Обычные POCO.

EP>>Смотри внимательней, я тебе дал прямую ссылку на сгенерированный код, там есть и исполняемый код.
НС>Где? Давай конкретно.

Например в самом начале:
public ITable<AlphabeticalListOfProduct>  AlphabeticalListOfProducts   { get { return this.GetTable<AlphabeticalListOfProduct>(); } }
public ITable<Category> Categories { get { return this.GetTable<Category>(); } }
...
[FreeTextTableExpression]
public ITable<FreeTextKey<TKey>> FreeTextTable<TTable,TKey>(string field, string text)
{
    return this.GetTable<FreeTextKey<TKey>>(
        this,
        ((MethodInfo)(MethodBase.GetCurrentMethod())).MakeGenericMethod(typeof(TTable), typeof(TKey)),
        field,
        text);
}

[FreeTextTableExpression]
public ITable<FreeTextKey<TKey>> FreeTextTable<TTable,TKey>(Expression<Func<TTable,string>> fieldSelector, string text)
{
    return this.GetTable<FreeTextKey<TKey>>(
        this,
        ((MethodInfo)(MethodBase.GetCurrentMethod())).MakeGenericMethod(typeof(TTable), typeof(TKey)),
        fieldSelector,
        text);
}
...

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

НС>>>Никаких додумок. В этой цитате С++ у тебя опять лучше всех.

EP>>Почему?
НС> Потому что там написано, что хоть у C# ситаксис лямбд и лаконичнее, но в целом С++ лучше.

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

НС>Классика жанра — любой аргумент дезавуировать "но в главном то он прав".


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

НС>>>А я тебя просил привести пример обратного. Ты не смог. ЧТД.

EP>>Мне может покаяться нужно что я привёл пример zero overhead?
НС>Не надо тебе каятся, просто надо признать что все что ты тут пишешь предельно однобоко. Надо быть слепым чтобы этого не замечать.

Я развеиваю мифы о C++ и делюсь знаниями — язык старый, сменилось много поколений стилей и т.п. Некоторые основывают свои высказывания хорошо если на основе фактов 25-летней давности. То что я развеиваю мифы только о нём — не означает что я считаю его "лучше всех остальных языков" и т.п. Без проблем использую C#, о чём даже в этой теме говорил.
Местные оппоненты же (разумеется не все) воспринимают это как "ACHTUNG! ВРАГ В ТРЕДЕ" и начинают заваливать демагогией, передёргиваниями и враньём
Re[189]: Тормознутость и кривость linq. Compile-time EDSL DB
От: Ночной Смотрящий Россия  
Дата: 12.07.16 16:17
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Заменяем

EP>
EP>return query<Table, Condition, Columns..., RightColumns...>{};
EP>
на

EP>
EP>return query<Table, Condition, RightColumns...>{};
EP>

EP>И получаем запрос
SELECT foo.number FROM foo WHERE foo.id>42


Жесть какая.

EP>public ITable<AlphabeticalListOfProduct> AlphabeticalListOfProducts { get { return this.GetTable<AlphabeticalListOfProduct>(); } }

EP>public ITable<Category> Categories { get { return this.GetTable<Category>(); } }
EP>public ITable<FreeTextKey<TKey>> FreeTextTable<TTable,TKey>(string field, string text)
EP>{
EP> return this.GetTable<FreeTextKey<TKey>>(
EP> this,
EP> ((MethodInfo)(MethodBase.GetCurrentMethod())).MakeGenericMethod(typeof(TTable), typeof(TKey)),
EP> field,
EP> text);
EP>}

Это просто набор хелперных методов. К запросам они отношения не имеют. Первые два — просто шоткаты, последний это вообще какие то заморочки с полнотекстовым поиском.

НС>> Потому что там написано, что хоть у C# ситаксис лямбд и лаконичнее, но в целом С++ лучше.

EP>Я не говорил "в целом лучше".

Ну алгоримическивыразительно лучше. Суть та же.

EP>Оппонент пытался оправдать раздутую реализацию лаконичностью использования на стороне вызова.


Что пытался тот оппонент оправдать вообще непонятно — он вообще постоянно какую то алогичную кашу на голову собеседникам вываливает. К нашему разговору это отношения не имеет.

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

EP>Я развеиваю мифы о C++

Ага, особенно ты развеивал мифы, когда влез в топик обсуждения CodeJam в ихнем форуме и начал сравнивать С# со своим С++. Самому не смешно?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.