Кресты / Говнокод #27340 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
void printParser(const wchar_t *fileName, const wchar_t *str, boolean showLineCharPos)
{
    ts::Parser parser;
    auto sourceFile = parser.parseSourceFile(fileName, str, ScriptTarget::Latest);

    ts::FuncT<> visitNode;
    ts::ArrayFuncT<> visitArray;

    auto intent = 0;

    visitNode = [&](ts::Node child) -> ts::Node {

        for (auto i = 0; i < intent; i++)
        {
            std::cout << "\t";
        }

        std::cout << "Node: " << wtoc(parser.syntaxKindString(child).c_str()) << " @ [ " << child->pos << " - " << child->_end << " ]" << std::endl;

        intent++;
        ts::forEachChild(child, visitNode, visitArray);    
        intent--;

        return undefined;
    };

    visitArray = [&](ts::NodeArray<ts::Node> array) -> ts::Node {
        for (auto node : array)
        {
            visitNode(node);
        }

        return undefined;
    };

    auto result = ts::forEachChild(sourceFile.as<ts::Node>(), visitNode, visitArray);
}

спортировал TypeScript парсер в C++ и ахренел от обьема работы :)

Запостил: ASD_77 ASD_77, (Updated )

Комментарии (188) RSS

  • а что больше никому не интересно компиляторо писание :)?
    Ответить
    • Ты просто забыл сделать SEO пост. Все смотрят на сток, а новые говнокоды без комментов в нём не появляются.
      Ответить
  • intent надо было глобалкой сделать, чтобы наверняка.
    Ответить
    • а че такое. мне и так нравиться... или зачем придумали лямбду в с++?
      Ответить
      • Лямду придумали, чтобы функциональщина. Только лямда курильщика захваченные переменные мутирует
        Ответить
        • > мутирует

          То есть меняет их? А правильно было бы ничего не менять никогда, потому что в функциональщине ценят иммутабельность?
          Ответить
          • Да

            Если foo(x) = 4, то желательно, чтобы оно всегда было 4, и не зависело бы от того, сколько раз ты это посчитал
            Ответить
            • А если это функция в полярных координатах, которая от количества витков по спирали зависит и разные результаты даёт в зависимости от того сколько ты там накрутил?
              Ответить
              • > А если это функция в полярных координатах, которая от количества витков по спирали зависит и разные результаты даёт в зависимости от того сколько ты там накрутил?

                Приведи реальный пример такой функции
                Ответить
                • На самом деле кол-во витков в такой функции будет выражаться как f(2π), f(4π), f(6π), ... Т.е. аргумент принимает разные значения.
                  Ответить
                  • А если это функция системного времени, или какой-нибудь rand? Ну или, например, алгоритм QSort (который рандомизированный)? У них всех будет каждый раз разный аутпут по очевидным причинам. Даже у кюсорта (сортировка нестабильная).
                    Ответить
                    • Функция системного времени это функция от "t", где "t" это системное время.
                      Функция имеет доступ только к своим параметрам.

                      Нестабильная сортировка может поменять местами два одинаковых объекта, но это не значит, что если ты ее несколько раз запустишь с одними и теми же аргументами, то получишь разный результат
                      Ответить
                      • > Функция системного времени это функция от "t"

                        Но я же явно туда ничего не передаю...

                        > это не значит, что если ты ее несколько раз запустишь с одними и теми же аргументами, то получишь разный результат

                        Да, это так. Вообще, т.к. в любом случае создастся новый массив, никакие сортировки уже не стабильные.

                        А про ранд я сам понял, там ничего рандомного-то и нет особо.

                        Ладно, а как в картину ФП будет вписываться функция генерации случайных чисел, основанная на вот таком:

                        https://www.random.org/audio-noise/

                        ?
                        Ответить
                        • >в любом случае создастся новый массив, никакие сортировки уже не стабильные.

                          не понял тебя.

                          sort(а,я,б) = [а,б,я]
                          sort(а,я,б) = [а,б,я]
                          sort(а,я,б) = [а,б,я]
                          [а,б,я] == [а,б,я]


                          стабильность это про то, можно ли поменять местами буквы "а" в массиве [а,а,я]

                          >Но я же явно туда ничего не передаю...
                          а это и не функция с точки зрения ма-те-ма-тика же

                          просто программеры ее так называют
                          Ответить
                          • Ну массивы мутабельные же, так что там нет никаких «тех же самых» элементов, которые на самом деле один адрес в памяти. А про стабильное-нестабильное я запутался и ошибся, конечно же, свойства сортировок сохраняются.
                            Ответить
                            • В нястоящем функциональном программировании массивы списки иммутабельны, а то и вообще ленивы.

                              Про audio-noise и вообще IO: https://www.haskell.org/tutorial/io.html.
                              Вкратце: все принципиально "ня-математические" действия (запросы к аппаратным ГСЧ, чтение файлов, печать символов, общение по сети, ...), которые по своей сути ня могут быть чистыми, выделяются в отдельный огороженный загончик и стыдливо прикрываются тряпочкой IO. Из этого загончика можно вызывать чистые функции, а вот няоборот — из чистых функций IO-действия — нельзя. Таким образом наш уютный чистый мир математических функций не шкварится.
                              Ответить
                              • > выделяются в отдельный огороженный загончик и стыдливо прикрываются тряпочкой IO

                                Вовсе нят. IO — это изумительно красивый хак, на самом деле, поскольку теоретически ничего нового в семантику чистого функционального языка он не вносит. Т.е. функции, работающие с IO, с точки зрения системы типов, пользователя и компинятора выглядят как приличные чистые функции, и они ведут себя так же (вернее, им не дают вести себя по-другому, см. ниже).
                                Формально, каждая функция, работающая с IO принимает на вход переменную типа RealWorld, и возвращает значение того же типа. Если убрать обёртку из монадок, получится что-то вроде:

                                main :: RealWorld -> RealWorld
                                main rw =
                                  (a, rw') = readFile rw "my_file.txt" -- в переменной rw якобы хранится содержимое файла, а функция readFile якобы это содержимое оттуда достаёт.
                                  rw'' = writeFile rw' "my_file.txt" "new contents"
                                  (b, rw''') = readFile rw'' "my_file.txt"
                                  rw'''


                                В примере выше, readFile с параметром "my_file.txt" может возвращать разные результаты, что вроде как чистым функциям нельзя. Но мы в неё передаём дополнительный аргумент realWorld, который каждый раз имеет разное значение. Значит всё в порядке.

                                Монада IO выполняет две функции: во-первых, она позволяет ня таскать этот параметр rw руками, а автоматизирует процесс. А во-вторых, что самое главное, она в принципе прячет от пользователя этот параметр внутрь модуля. Таким образом, она не позволяет юзеру взять, и переиспользовать одно и то же значение rw. Ибо если бы юзер мог это сделать, обман бы раскрылся. Но поскольку доступ к этому значению имеют только доверенные функции из стандартной библиотеки, которые используют его "правильно", иллюзия сохраняется. На самом деле тип RealWorld — пустышка, и, увы, состояние мира на 2011 год там не хранится, а жаль.
                                Ответить
                                • Подход с монадами — не единственно возможный. В Mercury (другом чисто функциональном языке) вместо них использовали структурные типы (задолго до растишки). Это тоже работает, но чуть менее изящно, т.к. требует менять систему типов.
                                  Ответить
                        • > Ладно, а как в картину ФП будет вписываться функция генерации случайных чисел, основанная на вот таком:

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

                          На а псевдослучайные числа в FP делаются точно так же, как и в императивщине:
                          https://hackage.haskell.org/package/random-1.2.0/docs/System-Random.html#v:random
                          (Обрати внимание на тип функции. g — это состояние генератора, a — полученное значение).
                          Только состояние PRNG (g) прячут не в статическую переменную, а в монаду.
                          Ответить
                      • Существуют реализации qsort(), использующие ГСЧ для выбора ведущего элемента — это позволяет им быть более стойким к целенаправленной деградации производительности (когда злоумышленник подбирает массив, ня котором быстрая сортировка деградирует до O(N^2)). Такие реализации действительно могут возвращать разные результаты для одних и тех же аргументов, но, конечно, с ФП они ня дружат.
                        Ответить
                        • Состояние ГПСЧ -- это вполне так параметр.

                          Ну и для юнит-тестов даже в крестах часто юзается явное состояние ГПСЧ. Иначе потом фиг воспроизведёшь почему упало.
                          Ответить
                          • Да, все бенчмарки я провожу исключительня с
                            uint64_t rand_next(uint64_t state)
                            {
                                return state* 6364136223846793005ull + 1442695040888963407ull;
                            }

                            (Как же бесят люди, считающие медиану времени для бенчмарков с детерминированными знячениями ヽ(‵﹏´)ノ!)

                            Ня дружат они в том смысле, что их ня получится сделать "чисто", без дополнительных явных параметров/хаков с IO/спросите бородатых девочек-функциональщиц.
                            Ответить
              • Это означает, что она помнит сколько ты там до этого накрутил. Это означает что у функции есть внешняя память, она обращается к глобальному состоянию программы. А значит она не pure. Хочешь такую функцию pure? Передавай в неё нужную память: foo(SKOLKO_KROOTIM, SKOLKO_UJE_NAKRUTILI). Как нетрудно догадаться, полученная функция будет чистой, и на одинаковом входе независимо от количества вызовов будет давать одинаковый результат.
                Ответить
        • В C++ хотя-бы ты явно выбираешь как их захватывать, в других мейнстримовых императивных "ваннаби-с-функционалкой" языках много хуже
          Ответить
        • если бы я не хотел мутировать я бы написал "[=](...)". А это значит что я хочу ее мутировать ... и никто без меня ее не смутирует. а значит она изолированна. а если она изолированна то она не делает обьект мутируемым 🙂
          Ответить
        • вот смотри люмбда курильщика у сепер писателей TypeScript-а и ничего - спят спокойно. потому что это то что нужно
          function gatherPossibleChildren(node: Node) {
                  const children: (Node | NodeArray<Node>)[] = [];
                  forEachChild(node, addWorkItem, addWorkItem); // By using a stack above and `unshift` here, we emulate a depth-first preorder traversal
                  return children;
          
                  function addWorkItem(n: Node | NodeArray<Node>) {
                      children.unshift(n);
                  }
              }
          Ответить
        • >Лямду придумали, чтобы функциональщина.

          Лямбда крестоговна это такая же функциональщина, как и обычная сишкофункция, ничего такого ФП-шного оно не добавляет, просто позволяет определять функцию по месту и сразу ее вызывать. Оно и захватывать хуйню может внешнюю и менять ее, т.е. нихуя такого там нет, любое использование лямбд можно переписать на банальные функции.
          Ответить
          • А напиши пожалуйста сишкокод (без гццизмов) который создает посреди функции другую функцию, которая захватывает часть параметров
            Ответить
            • > А напиши пожалуйста сишкокод (без гццизмов) который создает посреди функции другую функцию, которая захватывает часть параметров

              Зачем мне создавать функцию в функции, если я могу просто написать код в том месте? Или функция должна быть рекурсивной т.е. уметь сама себя вызывать? Не, ну можно в принципе переделать вот ту хуйню https://www.govnokod.ru/19299 чтоб там гнутые расширения не использовались, и свой стек хуйнуть там для адресов возврата.

              https://ideone.com/yqAHZq - можешь в вижуалстудии проверять
              Ответить
              • >Или функция должна быть рекурсивной т.е. уметь сама себя вызывать? Не,
                Чтобы передать её куда-то?
                Ответить
                • Куда? Если ты крестоговняную лямбду, юзающую часть параметров из скоупа самой ф-ции будешь передавать через return куда-то, то у тебя при ретурне проебуется стекфрейм функции, и у тебя будет UB. Если вызывать какую-то функцию и ей передавать, то вот эта срань с goto может вполне передавать метки другой такой же срани с goto, ну а если ты хочешь передавать в нормальные Си-функции какбы-указатель на эту срань, то можно сделать интерпретатор FORTH какой-нибудь, или еще какую-нибудь такую ебень, которая б со своим стеком со стекфреймами жила, который из сишки виден как глобальный массив, и вот этой поебенью можно что-угодно куда-угодно передавать, но это будет уже не обычная функция
                  Ответить
                  • Макака говорит: реализуй йажа callable в плейн си не реализуя другого языка.
                    Ответить
                    • Можно препроцессор на Си реализовать, который транслирует Си в Си-с-говнолямбдами. Так устроит?
                      Ответить
                      • Нутк ты опиши как эти говнолямбды будут реализованы? Как вызовы процедур? А захват скопа как будет устроен?
                        Кстати что с захватом скоупа у йажа колабл?
                        Ответить
                        • >Нутк ты опиши как эти говнолямбды будут реализованы?

                          Как функции, которые где-то там генерируются.

                          >А захват скопа как будет устроен?

                          Указателями на переменные скоупа.
                          Ответить
                          • Собственно, крестолямбды так и работают. Если куда-то передается лямбда, которая может читать, или читать-писать переменные в скоупе ф-ции, то там должны быть указатели этих переменных (или в крайнем случае хотя бы один указатель на стекфрейм, если переменные в стекфрейме размещены известно как).
                            Ответить
                  • Почему через return?
                    Я описал лямбду, которая захватила нужные мне переменные (она же кложа) причем ровно так, как я попросил (по референсу или копироваием) и я передал ее в функцию, которая ее как-то использовала
                    Ответить
                    • А если у тебя та функция записала лямбду в массив указателей на функции, и ты потом вышел и из той функции, и из функции с кложей и потом откуда-то хуй знает откуда решил вдруг вызвать ту свою лямбду по указателю, у тебя случится багор. Тебя такое устраивает?
                      Ответить
                      • Устраивает, я же понимаю что в сишечке и крестах чудес не бывает.
                        Если я верну указатель на что-то, что есть у меня на стеке, и потом выйду, то указатель укажет в жопу.

                        Это же не жабки с шарпами, где захваченные переменные живут, пока живет лямбда (отличный способ запутаться, и потечь памятью)
                        Ответить
                        • Так в JS GC.

                          Во всех языках с GC можно кложей захватить пол стекфрейма, положить кложу в кучу, выйти из функции, и вызвать кложу.

                          Все твое говно сохранится
                          Ответить
                  • > Если ты крестоговняную лямбду, юзающую часть параметров из скоупа самой ф-ции будешь передавать через return куда-то, то у тебя при ретурне проебуется стекфрейм функции, и у тебя будет UB.
                    Вовсе ня обязательно.
                    auto get_callback(std::string name)
                    {
                        auto msg = "Hello, " + std::move(name);
                    
                        auto lambda = [msg = std::move(msg)]() {
                            std::cout << msg << std::endl;
                        };
                    
                        std::cout << "Local msg: " << msg << std::endl;
                        return lambda;
                    }
                    
                    int main()
                    {
                        auto lambda = get_callback("World");
                        std::cout << "Calling lambda: ";
                        lambda();
                        std::cout << std::endl;
                    }

                    https://wandbox.org/permlink/lCNDWAAjUflyrsUq
                    Ответить
                    • Так это ж фигня полная, лямбда просто себе эту переменную забрала, и функция (или какая-то другая лямбда в той же функции) с ней уже нихрена не сделает.

                      И кстати, где будет адрес переменной msg после этого std::move в лямбде? В стекфрейме main? В хипе?
                      Ответить
                      • > и функция с ней уже нихрена не сделает.
                        Функция с ней ничего сделать ня сможет даже в теории, потому что по условиям задачи лямбда возвращается через return (ノ´ヮ`)ノ*: ・゚.

                        > или какая-то другая лямбда в той же функции
                        А для такого достаточно завернуть msg в shared_ptr и убрать std::move(msg). Сможешь ходить десять лямбд возвратить вектором.

                        > И кстати, где будет адрес переменной msg после этого std::move в лямбде? В стекфрейме main? В хипе?
                        Адрес — нигде. Сама строка msg будет лежать в объекте lambda — в стекфрейме main, в данном случае. Ну, если быть совсем точной — в этом примере компилятор эту лямбду заинлайнит, и никакого объекта lambda в асме ня будет.
                        Ответить
                        • > Функция с ней ничего сделать ня сможет даже в теории, потому что по условиям задачи лямбда возвращается через return (ノ´ヮ`)ノ*: ・゚.

                          Она-то может и возвращаться через return, но не сразу. Сначала она может куда-то передаваться, кто-то там эту лямбду повызывает, а потом уже та функция может что-то опять поделать с локальными переменными, и уже потом возвращать через return эту лямбду. Так что надо эти мувы делать именно при возврате, а не вот просто сразу.

                          > А для такого достаточно завернуть msg в shared_ptr и убрать std::move(msg). Сможешь ходить десять лямбд возвратить вектором.

                          Референс каунтер, коим этот shared_ptr является - уже анскильно и попахивает GC. Так-то можно все локальные переменные ф-ции через большой malloc выделять, завести счетчик на тот malloc-нутый адрес который декрементится когда лямбда юзающая маллокнутые хрени уничтожается, ну и надо регистрировать ситуации, когда на лямбды нет нигде указателей (счетчик для локальных переменных выделенных в хипе равен 0 - никакие лямбды уже его не юзают - можно освободить память). Эта питушня мне напоминает концепцию ownership из Rust https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html

                          > Адрес — нигде. Сама строка msg будет лежать в объекте lambda — в стекфрейме main, в данном случае.

                          А если лямбда будет не из main а из какой-то другой функции доставаться, и та другая функция будет ту лямбду возвращать еще через return и так далее, то это всё будет через стек копироваться, да? Это анскильно.

                          А если ту лямбду в глобальную std::function присвоить, где будет храниться ее msg?
                          Ответить
                          • > Так что надо эти мувы делать именно при возврате, а не вот просто сразу.

                            Т.е. нужно две почти одинаковые лямбды, одну мы передаем в функции как аргумент (притом ту лямбду лучше никуда в глобальные или статические переменные не присваивать, потому что она будет уже невалидной при выходе из скоупа той ф-ции в которой ее создали), другую в самом конце перед ретурном с std::move объявляем и возвращаем. Какой багор )))
                            Ответить
                            • слушай, но ведь лямбды это просто сахар для пары указатель-на-функцию + какие-то данные

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

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

                              Страння, конечно: тебе показывают удобный, production-ready, инструмент, позволяющий сократить количество кода и ошибок, а ты в ответ нячинаешь яростно выдумывать миллиарды корнер-кейсов, когда этот инструмент работает не идеально. При этом в качестве няпобедимого образца ты демонстрируешь https://ideone.com/yqAHZq, в котором гордо городишь свой собственный стек. Это, няверное, должно быть образцом краткости, читаемости, удобства и производительности?
                              Ответить
                              • > Страння, конечно: тебе показывают удобный, production-ready, инструмент, позволяющий сократить количество кода и ошибок, а ты в ответ нячинаешь яростно выдумывать миллиарды корнер-кейсов, когда этот инструмент работает не идеально.

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

                                > При этом в качестве няпобедимого образца ты демонстрируешь https://ideone.com/yqAHZq, в котором гордо городишь свой собственный стек. Это, няверное, должно быть образцом краткости, читаемости, удобства и производительности?

                                О нет, я это естественно не приводил как образец читаемости, удобства и производительности. Это не более чем пример того, как можно сделать.
                                Ответить
                                • > Вот именно, в крестах это всё неидеально.
                                  А ты хочешь одну кнопочку "сделать хорошо"? Ну извини, такого ня придумали ещё. Лямбды — это очень удобный и эффективный инструмент, позволяющий существенно снизить количество бройлер-плейта. То, что они ня работают как лямбды в языке с ГЦ — так извините, у нас не язык с ГЦ.

                                  > типа что вот если мы передаем лямбду-захватывающую-локалки в другие функции, то вот те другие функции ни в коем случае не должны
                                  Сделай [=] и спокойно присваивай что угодно чему угодно ценой лишних копирований. Чем эффективнее должен быть твой код — тем больше нядо писать, это в любом языке так. Если тебе важен каждый передвинутый байтик, то очевидно, что тебе придётся подробно объяснять компилятору, какие байтики двигать нядо, а какие ня надо (тут вызываю штатных девочек-волшебниц для демонстрации мощи Хаскелля и ко).

                                  > Чтоб корнер-кейсов не было, достаточно просто взять язык с GC и не сношать себе мозг всем этим безобразием.
                                  Будто бы в языках с GC корнер-кейсов и мозговыносящего няочевидного поведения меньше.

                                  > Это не более чем пример того, как можно сделать.
                                  А зачем он? Кажется, то, что C — тьюринг-полный ЯП, никто ня оспаривает. Через setjmp()/longjmp() и портянки макросов к сишке хоть полноценный гц можно прикрутить.
                                  Ответить
                                  • > Сделай [=] и спокойно присваивай что угодно чему угодно ценой лишних копирований.

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

                                    > А зачем он? Кажется, то, что C — тьюринг-полный ЯП, никто ня оспаривает. Через setjmp()/longjmp() и портянки макросов к сишке хоть полноценный гц можно прикрутить.

                                    Ну так я его не с нуля писал сейчас. История того говнокода восходит к https://www.govnokod.ru/19299 - я его просто слегка переделал, избавив от гцц-измов. В подписи к тому говнокоду написано, зачем это: "Этим кодом я доказывал одному типу какой-то бред, связанный с рекурсией. Типа он считал что ее нельзя реализовать через сраные циклы со стеком(или может просто хотел посмотреть на такую реализацию)."
                                    Ответить
                                    • Можно, конечно. В этом и суть — что сишки, что крестов: нам дают ружьё и полную свободу действий. Лямбды — это просто маленький кусочек ружья, который облегчает его использование, но вот прострелить себе ногу можно что с лямбдами, что без них. Если ня нравится думать — действительно, можня спокойно уйти на JS и Python. А говорить, что лямбды ня нужны, потому что они не работают как в JS сто лет без лямбд писали и дальше без них обойдёмся — это в точности изображать знаменитую бабку из https://www.youtube.com/watch?v=2Dm0Z2yyIwE.

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

                                        Лямбды крестов ничего принципиально не меняют, это такой какбы сахарок над объявлением статической функции, только такая функция не имеет никакого имени в рамках единицы трансляции, и указатель такой ф-ции присваивается в какую-то переменную, или же мы сразу вызываем эту лямбду, и тогда даже указателей никаких нет (но и с функцией такое тоже будет, если она заинлайнится). Захват переменных из скоупа это неявная передача указателей на эти переменные в лямбду.

                                        Вот если б завезли лямбды как в языках-с-GC, когда можно что-то позахватывать лямбдой и не думать над тем, вышли мы из стекфрейма или не вышли из стекфрейма... но тут без какого-то GC или рефкаунтера мало что сделать можно. Рефкаунтер-то по сути огрызок GC, только циклические ссылки он чистить не сможет никак
                                        Ответить
                                        • Разумеется, они ничего принципиально не меняют. Лямбды в крестах просто сильно облегчают жизнь — именно тем, что то, что раньше делалось вручную, теперь можня делать простым и коротким выражением. Вместо того, чтобы писать сто строчек в разных местах, теперь можно няписать десять в одном.

                                          > Вот если б завезли лямбды как в языках-с-GC
                                          Я уже говорила выше: хочешь GC — сделай себе GC на shared_ptr, а лямбды в этом помогут.
                                          auto get_callback() {
                                              auto local = std::make_shared<X>(16);
                                          
                                              auto lambda_1 = [local] { ... };
                                              use_lambda(lambda_1);
                                          
                                              auto lambda_2 = [local] { ... };
                                              use_lambda(lambda_2);
                                          
                                              return [local] { ... };
                                          }

                                          — всё, ни о чём больше думать ня надо, код максимально короткий и выразительный. За простоту платим, во-первых, няобходимостью аллокаций (ня обязательно в куче, правда: можня сделать свой собственный аллокатор, который будет выделять память в глобальном массива байтиков, няпример), во-вторых — подсчётом ссылок при создании/уничтожении local.
                                          Ответить
                                          • Шаред поинтеры это не полноценное GC. Если лямбда1 хранит шаред поинтер на лямбду2, лямбда2 хранит шаред поинтер на лямбду1, и больше никто не хранит шаред поинтеров ни на лямбду1 ни на лямбду2, будет утечка памяти.
                                            Ответить
                                            • пушо это не GC а RC.

                                              Reference cycles RC решать не умеет (у ябла для этого были "слабые" ссылки, g: "strong weak dance").

                                              GC называет такие штуки "isle of isolation", и выпиливает их.
                                              Ответить
                                            • А если удариться головой об стену — будет утечка мозгов.

                                              Для разрешения циклических зависимостей существует std::weak_ptr. Но всем будет гораздо проще, если этих зависимостей ня будет вообще, как в приведённом мною примере.
                                              Ответить
                                              • > Для разрешения циклических зависимостей существует std::weak_ptr. Но всем будет гораздо проще, если этих зависимостей ня будет вообще, как в приведённом мною примере.

                                                А они вполне могут быть. Для std::weak_ptr то мы еще должны заранее знать, что вот эта лямбда1 владеет лямбда2 (на нее std::shared_ptr), а вот лямбда2 уже не владеет лямбда1 (на нее std::weak_ptr), а мы это можем не знать на этапе компиляции, связи между лямбдами могут формироваться динамически в процессе исполнения. Могут быть какие-то длинные кольца с этих лямбд, которые друг на друга ссылаются. Вот допустим образовался кольцевой связный список из этих лямбд, и на какую-то из лямбд указывает что-то, и допустим оно перестало указывать.
                                                something
                                                   |
                                                   V
                                                lambda1 -> lambda2 -> lambda3 -> lambda4
                                                   ^                                |
                                                    \_______________________________/

                                                Какая из связей должна быть weak_ptr? Очевидно, чтобы этот цикл разорвался при убирани связи something-> , weak_ptr должен быть между lambda4 и lambda1

                                                something
                                                   |
                                                   V
                                                lambda1 -> lambda2 -> lambda3 -> lambda4
                                                   ^                                |
                                                    \.............................../

                                                Но что если этот поинтер из something будет перставляться с лямбды на лямбду? Хо-хо-хо, тогда и weak_ptr должен мигрировать, т.е. нужно пробежать весь кольцевой список и переставить этот weak_ptr
                                                .       something
                                                             |
                                                             V
                                                lambda1 .> lambda2 -> lambda3 -> lambda4
                                                   ^                                |
                                                    \_______________________________/

                                                Разве не охуенно? А если у нас не кольцевой связный список из лямбд, а вообще произвольная поебень может из этих ссылок сконструироваться? И GC бы эту проблему просто брал бы и решал, а в крестах тут всплывает какая-то непонятная херота, хоть GC пиши.
                                                Ответить
                                                • Так что чтобы не задумываться о том, что вот у меня лямбды говно и вот в таком сценарии использования они поломаются и поэтому тут нужен костыль, а в таком сценарии тоже поломаются и нужен такой костыль, а в таком сценарии вообще хуй его знает что делать... может лучше брать язык с GC, где всё порешается само?
                                                  Ответить
                                                  • Предлагаю использовать язык "Basic" в первой его редакции.

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

                                                    В "GC" ты можешь случайно зацепить лямбду оставив ее в какой-нить коллекиции, и она утащит за собой 300 мегабайт.

                                                    В крупном проекте по любасу нужно понимать что и где лежит и какие есть ссылки.

                                                    В том же ябле, например, были когда-то четкие правила на что нужно иметь weak ref, а на что нет.
                                                    Ответить
                                                    • Лучше уж ассемблер. Там даже переменных как таковых нет, есть только регистры и память.
                                                      Ответить
                                                        • На MIPS архитектуре стека нет. Ты сам себе его изобретаешь, если он тебе нужен. https://stackoverflow.com/a/52581825

                                                          > MIPS unlike other archs doesn't have a push or pop register/immediate instruction. So you rely on managing the stack yourself. This is actually noted in most of the arch outside of mul/div where your registers don't have a specific use, just a suggested way to use it. Now if you used it however you wanted, you would break something if you tried to integrate with C for example.
                                                          Ответить
                                                        • Тут есть тонкая грань того, что можно считать "стеком". В x86 весь стек — это просто сахарок над джвумя инструкциями, каких-то магических знячений rsp/esp/ss:sp ня имеют.
                                                          Ответить
                                                          • > В x86 весь стек — это просто сахарок над джвумя инструкциями, каких-то магических знячений rsp/esp/ss:sp ня имеют.

                                                            В x86-процессорах есть особый механизм кеширования, который завязан на call/ret

                                                            https://www.agner.org/optimize/microarchitecture.pdf - см. 3.16 Returns (all processors except P1)
                                                            Ответить
                                                        • штеуды - специалированные процы, а в мипсах это просто конвешн
                                                          Ответить
                                                  • Всё в точности так, как я и говорила:

                                                    "Страння, конечно: тебе показывают удобный, production-ready, инструмент, позволяющий сократить количество кода и ошибок, а ты в ответ нячинаешь яростно выдумывать миллиарды корнер-кейсов, когда этот инструмент работает не идеально."

                                                    На лицо неприятие всего нового, даже когда оно нужно и полезно.

                                                    А обмен корнер-кейсами можно проводить хоть до бесконечности: сделаешь substr(0, 10) от гигабайтной строки в языке-с-GC-ня-надо-думать — получишь утечку гигабайта.
                                                    Ответить
                                                    • > "Страння, конечно: тебе показывают удобный, production-ready, инструмент, позволяющий сократить количество кода и ошибок, а ты в ответ нячинаешь яростно выдумывать миллиарды корнер-кейсов, когда этот инструмент работает не идеально."

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

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

                                                        > Любой код с лямбдой можно известно как переписать на код с вызовом функции, объявленной где-то в этом же файле.
                                                        Любой код с сишки можня переписать на JavaScript. Означает ли это, что сишка не нужна?

                                                        > Инструментом можно было б считать те же метаклассы, они вот реально много чего в языковых возможностях меняют
                                                        Это не инструмент, это банальный сахарок над созданием классов где-то в текущей единице трансляции, ничего концептуально нового в язык не добавляющий. Любой код с метаклассом можно известно как переписать на код с явным class, объявленным где-то в этом же файле.
                                                        Ответить
                                                        • > Любой код с сишки можня переписать на JavaScript.

                                                          Нет. Сигфолт сишки от вылезания за пределы массива на JavaScript не перепишешь. И вообще, в JS указателей нифига нет.
                                                          Ответить
                                                          • указатели можно сэмулировать

                                                            любой код на тюринг полном языке можно переписать на другой тюринг полный язык, и наверняка ты это и без меня знаешь
                                                            Ответить
                                                          • Ну как это ня перепишешь, когда перепишешь, причём очень просто?
                                                            let arr = new Proxy([0, 1, 2, 3], {
                                                                get: function(obj, idx) {
                                                                    if (idx < 4) {
                                                                        return obj[idx];
                                                                    }
                                                            
                                                                    throw 'Segmentation fault';
                                                                }
                                                            });
                                                            
                                                            console.log(arr[1]);
                                                            console.log(arr[15]);


                                                            А указатели вообще ня нужны: от них одни только сегфолты. Здоровым, адекватным джаваскриптерам вполне хватает ссылок.
                                                            Ответить
                                                        • > Это не инструмент, это банальный сахарок над созданием классов где-то в текущей единице трансляции, ничего концептуально нового в язык не добавляющий.

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

                                                          Вообще, все языки это сахарок над машинным кодом, кроме верилога какого-нибудь, который уже сахарок над топологией соединения и конфигурацией ячеек.
                                                          Ответить
                                                          • > Ха. Руками писать вместо метаклассов некую фигню-которая-синтезируется-метаклассами будет существенно сложнее, чем написать функцию, которая чего-то принимает как аргументы и что-то возвращает, и пользоваться ей вместо лямбды.
                                                            Пусть сложнее, а что концептуального нового-то? Вот я ня так давно писала генерацию методов у классов:
                                                            #define ENTITY_EVENT_FIELD_GETTER(getter_name, entity_state_field_name)                        \
                                                                static int32_t getter_name ## FromEntity(const entityState_t & eventEnt) noexcept          \
                                                                {                                                                                          \
                                                                    return eventEnt.entity_state_field_name;                                               \
                                                                }                                                                                          \
                                                                int32_t getter_name() const noexcept {                                                     \
                                                                    return getter_name ## FromEntity(getEventEntity());                                    \
                                                                }

                                                            — как видишь, все эти ваши хвалёные метаклассы прекрасня эмулируются старым добрым препроцессором, а, следовательня, не нужны.
                                                            Ответить
                                                              • И что? Что концептуально нового добавляют в язык метаклассы — что без них нельзя сделать ручками/препроцессором?
                                                                Ответить
                                                                • Если ставить вопрос таким боком, концептуально нового и сишка с ассемблером не добавляет. Можно упороться и всю программу вместе с ELF заголовком в hex-редакторе написать.

                                                                  Между функцией в Си и лямбдой в каком-нибудь JS есть очень существенная разница, а между функцией в Си и лямбдой крестов разницы по-сути никакой нет, только небольшой плюс к удобству. Не, можно конечно и на Си и на крестах какими-то кривыми костылями с препроцессингом и кодогенерацией реализовать лямбду с рефкаунтингом и GC, только это уже будет совсем другая сущность, имеющая мало общего с той лямбдой, которая есть в крестах.

                                                                  И метаклассы тоже можно к имеющимся крестам прикостылить, сделав транспайлер из одного стандарта крестов в другой
                                                                  Ответить
                                                                  • > Если ставить вопрос таким боком, концептуально нового и сишка с ассемблером не добавляет.
                                                                    Да. Из этого можно сделать вывод, что ни сишка, ни ассемблер ня нужны: всем нужно срочно писать программы в машинных котах. Рекомендую WCT.

                                                                    > Между функцией в Си и лямбдой в каком-нибудь JS есть очень существенная разница
                                                                    Концептуально — нет никакой разницы. Джаваскриптовские замыкания (это ня то же самое, что и лямбды) можно, вооружившись препроцессором и такой-то ока-сан, сэмулировать и на C++, и на C.
                                                                    Ответить
                                                                  • > а между функцией в Си и лямбдой крестов разницы по-сути никакой нет, только небольшой плюс к удобству.
                                                                    Большой плюс к удобству, отсутствие длинного бройлер-плейта, статические гарантии (няпример, что ты ня забудешь прокинуть локальную переменную в инициализатор структурки-контекста), простой и удобный синтаксис определения списка захвата. Ну и давай посмотрим на реальный, однозначный пример:
                                                                    int a;
                                                                    std::string b;
                                                                    std::unique_ptr<float> c;
                                                                    float d;  // Ня будем захватывать, для примера
                                                                    
                                                                    // Инициализация a, b, c...
                                                                    
                                                                    // Лямбда:
                                                                    auto lambda = [a, &b, c = std::move(c)] { /* кот */ };
                                                                    
                                                                    // Эмуляция:
                                                                    struct LocalCtx_1 {  // Ня забудь сменить номер для следующей "лямбды"!
                                                                        int a;   // Люблю повторять код по два раза.
                                                                        const std::string & b;  // Люблю повторять код по два раза.
                                                                        std::unique_ptr<float> c;
                                                                        
                                                                        void operator()() const {
                                                                            /* кот */
                                                                        }
                                                                    };
                                                                    auto nyambda = LocalCtx_1{a, b, std::move(c)};

                                                                    В ручном подходе имеем целый ворох способов выстрелить себе в ногу (помимо тех, о которых ты тут целый день распиняешься), нявскидку:
                                                                    1. Можно забыть иняциализировать "c": получишь nullptr внутри функции.
                                                                    2. Каждую переменную из списка захвата упоминяешь два раза: в определении структуры и инициализации.
                                                                    3. Меняешь тип локальной переменной — ня забудь пройтись по всем таким "лямбдам" и ручками меняй его.
                                                                    4. Хочешь получать c по ссылке, а не мувать? Ня забудь убрать std::move() и изменить определение. Аналогичня — для всех остальных переменных.

                                                                    Все эти проблемы крестовая лямбда эффективно решает: забыть инициализировать ничего нельзя, список захвата пишешь ровно один раз, все типы выводятся автоматически, способ захват чётко и ясно виден ровно в одном месте, и, что важно, прямо перед определением тела функции.
                                                                    Ответить
                                                                    • // тут набросаем локалок
                                                                      #define P1(name,...) \
                                                                      struct name {##__VA_ARGS__
                                                                      
                                                                      // тут впишем код
                                                                      #define P2(code) \
                                                                      void operator()() const code
                                                                      
                                                                      P1(LocalCtx1, int a; const std::string & b; std::unique_ptr<float> c;)P2({ /* кот */});
                                                                      auto nyambda = LocalCtx_1{a, b, std::move(c)};

                                                                      Еще можно кое-какой хренью делать так, чтобы:
                                                                      P1_NEXTGEN(LocalCtx1, a; &b; c;)P2({ /* кот */});
                                                                      auto nyambda = LocalCtx_1{a, b, std::move(c)};
                                                                      // чтобы 
                                                                      //P1_NEXTGEN(LocalCtx1, a; &b; c;)P2({ /* кот */}); ---> P1(LocalCtx1, decltype(a) a; decltype(b) &b; decltype(c) c;)P2({ /* кот */});


                                                                      Я даже знаю, через какой препроцессорный костыль это можно было б сделать. Можно попробовать запилить такого макроговна, но как-то лень
                                                                      Ответить
                                                                      • Поздравляю! Ты изобрёл кривое, няудобное, нярасширяемое и няподдерживаемое макроговно, которое при взгляде с расстояния в 16 километров и в небольшом подпитии слегка няпоминает уже существующую и хорошо работающую лямбду. И всё ради того, чтобы доказать, что лямбда ня нужна.
                                                                        Ответить
                                                                        • Это потому что препроцессор говно. Дайте мне нормальную рефлексию(доступ к AST) с полным по-Тьюригну языком для компилтайм-конструирования хреней, и можно эту лямбдию легко реализовать без каких-либо особенных затрат. И на такой хрени можно бы было делать реально мощные вещи, а не только какие-то лямбды.
                                                                          Ответить
                                                                          • А что, если создатели языков программирования не хотят, чтобы что-то подобное появилось? Потому что тогда все остальные языки не будут нужны, и программисты станут метапрограммистами...
                                                                            Ответить
                                                                          • И тогда в каждом проекте будут свои собственные лямбды, свои собственные structural bindings, auto ещё можно своё запилить, свои метаклассы, своё няследование, свои вызовы функций...

                                                                            Представляешь, как круто: вместо того, чтобы зубрить один C++, придётся в каждом проекте зубрить свой собственный C++! Зубрилки визжат от радости.

                                                                            В абсолютном большинстве случаев стандартное лучше нястандартного. Лучше выучить один стандартный сахарок и везде использовать его, чем зубрить двадцать самописных сахарков, решающих одно и то же, но по-разному и с кучей неочевидных нюансов каждый. В реальном мире гомоиконность и прямая модификация AST — удел либо развлекательного программирования, либо фанатиков, не видящих дальше своего крошечного мирка.
                                                                            Ответить
                                                                            • не думаю, это будет развиваться по законам библиотек где будет де-факто стандарт (или несколько конкурирующих) и все будут их знать
                                                                              Ответить
                                                                              • Это будет NIH. Как сейчас каждый FAANG и каждый мнящий себя FAANGом переизобретает стандартную либу ("folly" и иже с ними) — так и с гомоиконностью будет тотальное переписывание синтаксиса C++.
                                                                                О чём тут говорить, если даже при наличии хорошо сделанной банальной лямбды в нашем сообществе из 3,5 человек уже нашёлся желающий её переписать ня макроговно — исключительно потому, что NIH?
                                                                                Ответить
                                                                                • >нашёлся желающий её переписать ня макроговно — исключительно потому, что NIH?

                                                                                  Исключительно чтоб показать, что даже кривым сишным препроцессором можно что-то похожее родить.
                                                                                  Ответить
                                                                                  • Да, имення так: тебе ня нравится крестолямбда, ты изобрёл вместо неё свою собственную макросню. Был бы ты крестотимлидом — твои джуны уже усердно учили бы, какой параметр в макросе отвечает за тип захвата.
                                                                                    Ответить
                                                                                • >Это будет NIH
                                                                                  Это все прекрасно но дело в том что с++ не развивается в сторону мощного метапрограммирования не потому что benevolent dictator решил что обезьянкам оно не нужно а потому что как я понял из ваших разговоров децентрализованый комитет не умеет в последовательный дизайн. По-моему лучше бы уже децентрализовались до конца и сообщество каталось на велосипедах и в ходе рыночных процесов рождались хуевые или не очень решения, если комитет делает то же самое только долго и с претензией на правильность
                                                                                  Ответить
                                                                                  • Медленное и долгое развитие — это в любом случае лучше, чем быстрый, чоткий, дерзкий Python 2 -> 3.
                                                                                    Комитет как раз централизован, просто он адски нуден и няповоротлив — не в последнюю очередь из-за того, что в нём сидит приличное количество контрибьюторов в компиляторы, которые ня каждый пропозал с забористой метушнёй первым делом хватаются за волосы и орут о том, как же они это говно будут реализовывать. Многие же пропозалы просто забывают, впрочем.

                                                                                    И да, 10000 обезьян за клавиатурами обязательня няпечатают Идеальный Стандарт, но это будет не при няшей жизни.
                                                                                    Ответить
                                                                                    • >Медленное и долгое развитие — это в любом случае лучше, чем быстрый, чоткий, дерзкий Python 2 -> 3.

                                                                                      для меня это выглядит как "медленное и долгое развитие"(велосипеды) и "очень медленное и бюрократизованное развитие"(комитет)

                                                                                      >И да, 10000 обезьян за клавиатурами
                                                                                      Это разговор в плоскости политики: как именно мы хотим управлять языком и если хотим демократично, то насколько прямой должна быть демократия.

                                                                                      Я хочу сказать что то что предлагает j123123 не является чем-то однозначно худшим чем то что есть сейчас и разговоры про NIH выглядят как рационализация твоей нелюбви к велосипедам
                                                                                      Ответить
                                                                                      • > для меня это выглядит как "медленное и долгое развитие"(велосипеды) и "очень медленное и бюрократизованное развитие"(комитет)
                                                                                        Ключевая разница в несовместимости. Единая и централизованная толпа макак — Комитет — делает хоть и условно, но совместимый и более-менее консистентный стандарт. А вот кто будет собирать по углам Гитхаба миллионы принципиально нясовместимых между собой поделий, полировать их и объединять во что-то более-менее прилично выглядящее — большой вопрос.

                                                                                        > и разговоры про NIH выглядят как рационализация твоей нелюбви к велосипедам
                                                                                        А что, есть люди, которые реально любят использовать велосипеды? Ну в смысле не писать их для развлечения или из большой нужды (когда ни stdlib, ни сторонние либы объективно ня подходят), а просто брать и совать в прод переизобретённые копии существующих и хорошо работающих вещей?
                                                                                        Ответить
                                                                                        • > то будет собирать по углам Гитхаба миллионы принципиально нясовместимых между собой поделий

                                                                                          Ну буст же собрали и он как-то стал стандартом де-факто...
                                                                                          Ответить
                                                                                          • Он стал де-факто стандартом просто потому, что был одной из первых (подозреваю, что без "одной из") либ, делающих древние кресты хоть чуть-чуть удобным ЯП. Точня так же, как PHP стал популярным ЯП потому, что был первым в своей нише.
                                                                                            Ответить
                                                                                        • >но совместимый и более-менее консистентный стандарт
                                                                                          >миллионы принципиально нясовместимых между собой поделий

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

                                                                                          >А что, есть люди, которые реально любят использовать велосипеды?

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

                                                                                    любопытно, как будет организована стондартизация крестговна в следующем цикле
                                                                                    Ответить
                                                                            • > И тогда в каждом проекте будут свои собственные лямбды, свои собственные structural bindings, auto ещё можно своё запилить, свои метаклассы, своё няследование, свои вызовы функций...

                                                                              Можно запилить стандартные лямбды, метаклассы и наследования в стандартной библиотеке на этой гомоиконности с модификацией AST.

                                                                              А если кто-то решит свои альтернативные лямбды делать, то это уже его личное дело. Никто ж не запрещает свои говностроки изобретать под каждый проект
                                                                              Ответить
                                                                              • > А если кто-то решит свои альтернативные лямбды делать, то это уже его личное дело. Никто ж не запрещает свои говностроки изобретать под каждый проект
                                                                                Именно. Только если с говностроками всё более-менее по-ня-тно (есть говнокласс, у говнокласса есть конструкторы/методы/деструкторы, открыла объявление и читай), то гомоиконность — это прямой путь к изобретению собственного говноязыка говнопрограммирования, который надо учить заново. И так ня каждом говнопроекте.

                                                                                В реальном мире гомоиконность и прямая модификация AST — удел либо развлекательного программирования, либо фанатиков, не видящих дальше своего крошечного мирка.
                                                                                Ответить
                                                                                • > Только если с говностроками всё более-менее по-ня-тно (есть говнокласс, у говнокласса есть конструкторы/методы/деструкторы, открыла объявление и читай), то гомоиконность — это прямой путь к изобретению собственного говноязыка говнопрограммирования, который надо учить заново. И так ня каждом говнопроекте.

                                                                                  Проблемы негров шерифа не волнуют. Ежели кто будет по мини-говноязыку изобретать на каждом говнопроекте, а потом искать зубрилок, которые эти говноязыки будут готовы расширять и писать на них, это уже его проблемы.
                                                                                  Ответить
                                                                                  • Не "если", а "когда", я уже привела тебе примеры переписываний стандартной либы. И это проблемы не негров, а программистов ня потенциально-гомоиконном C++. Программистам эти "фичи" принесут гораздо больше вреда, чем пользы, а, следовательно, в языке они ня нужны.
                                                                                    Ответить
                                                                                    • >И это проблемы не негров, а программистов ня потенциально-гомоиконном C++. Программистам эти "фичи" принесут гораздо больше вреда, чем пользы, а, следовательно, в языке они ня нужны.

                                                                                      Как я уже сказал, проблемы негров шерифа не волнуют. Если программисты такие ебланы, что понаделают какого-то нечитаемого мета-говна на гомоиконах, то это ИХ ПРОБЛЕМЫ. Значит пусть делают из этого какие-то оргвыводы и договариваются о том, что надо б вот эту готовую мета-либу использовать, а не свои велосипеды через модификацию AST городить. Или можно вообще отключить эту фичу с модификацией AST флагом компилятора (или забыть о ее существовании), и писать без нее.
                                                                                      Ответить
                                                                                      • Процитирую твою цитату копипасты, с которой, судя по частоте употребления, ты согласен:
                                                                                        > C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений. Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист.
                                                                                        Итого, ты против C++, потому что в нём слишком много нагромождений, которые нядо зубрить. В качестве решения ты предлагаешь прямое управление AST, чтобы любая закорючка могла означать что угодно, правильня?
                                                                                        Ответить
                                                                                        • >Итого, ты против C++, потому что в нём слишком много нагромождений, которые нядо зубрить.

                                                                                          Не совсем так. Там не просто слишком много нагромождений, оно еще и хуево спроектировано. Мне например не нравится механизм обработки исключений. Мне не нравится что std::string не умеет CoW. Мне не нравятся тупые и долбанутые правила наследований, не нравится ООП в реализации C++ и вообще в целом ООП мне не нравится, это какой-то сраный мусор, который надо облить бензином, поджечь, обоссать, залить бетоном и скинуть на дно Марианской впадины.

                                                                                          > В качестве решения ты предлагаешь прямое управление AST, чтобы любая закорючка могла означать что угодно, правильня?

                                                                                          Когда мне это реально надо, тогда да. В целом кресты - хуево спроектированный язык, где надо в уме держать кучу говноньюансов всякого говна, и лучше сделать другой язык.
                                                                                          Ответить
                                                                                          • > В целом кресты - хуево спроектированный язык, где надо в уме держать кучу говноньюансов всякого говна, и лучше сделать другой язык.
                                                                                            Да. Только немного ня ясно, почему тебя особення обозлил один из нямногих действительно грамотно и удобно спроектированных сахарков в виде лямбды.

                                                                                            > Когда мне это реально надо, тогда да.
                                                                                            А неограниченное управление AST реально нужно примерно в 0% случаях, потому что изобретение DSL на пустом месте для решения частной задачи — это прямой путь к няподдерживаемому говну, которое читать сможет примерно 1 человек в мире и то только один месяц после няписания.
                                                                                            Ответить
                                                                                            • >Только немного ня ясно, почему тебя особення обозлил один из нямногих действительно грамотно и удобно спроектированных сахарков в виде лямбды.

                                                                                              Да я и не обозлился.

                                                                                              >А неограниченное управление AST реально нужно примерно в 0% случаях, потому что изобретение DSL на пустом месте для решения частной задачи — это прямой путь к няподдерживаемому говну, которое читать сможет примерно 1 человек в мире и то только один месяц после няписания.

                                                                                              Так я и не призывал каждый раз свой велосипед изобратать. Когда мне нужно было на контроллере сделать быстрое преобразование Фурье, я почему-то не начал писать свою реализацию с нуля, я поискал по гитхабу, нашел некоторое количество либ, решающих мою задачу, выбрал одну из них и всё. Если б в условном языке X изначально не было фичи Y но она была б реализуемой через механизм управления AST, и мне такая фича была б сильно нужна, я б тоже первым делом пошел искать мета-либу, которая б эту возможность добавляла. Не вижу между этими двумя кейсами никакой существенной разницы
                                                                                              Ответить
                                                                                              • > Да я и не обозлился.
                                                                                                Ну ладня.

                                                                                                > Не вижу между этими двумя кейсами никакой существенной разницы
                                                                                                Разница в том, что "обычная" либа не изме-ня-ет сам язык. Какую бы ты крестолибу ня взял — const у тебя останется модификатором константности, шаблоны будут объявляться через template<...>, а в квадратных скобочках будут либо объявления массивов, либо индексация, либо лямбда (ой, ня очень хороший пример (ノ*°▽°*)).
                                                                                                А вот с металибами всё будет по-другому: они по определению будут добавлять в твой проект новые закорючки, новые скобки, новые модификаторы и так далее. По отдельности это ещё можно терпеть, но вот когда ты подключишь пяток таких стильных модных лисподобных либ — ты внязапно обнаружишь, что вместо любимой сишечки ты пишешь ня какой-то дикой солянке из нясочетающихся языковых элементов, придуманных вообще никак не общающимися друг с другом людьми. И если уж даже вроде как совещающийся Комитет сделал говно, то толпа несвязанных макак сделает твою жизнь нявыносимой.
                                                                                                Ответить
                                                                                                • > А вот с металибами всё будет по-другому: они по определению будут добавлять в твой проект новые закорючки, новые скобки, новые модификаторы и так далее.

                                                                                                  Мета-либы в гомоиконном языке через S-expr делать, и тогда новые закорючки появляться не будут. Какая-нибудь лямбда может записываться как-нибудь так например:

                                                                                                  (= lambda_var ((metalib :: labmda), (a, &b, c), (some_code)))


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

                                                                                                  Слишком категоричные и общие утверждения. Тут всё завист от конкретики, как эта работа с AST реализована, каков изначальный синтаксис и система типов в конкретном ЯП, насколько интуитивно синтаксис отображаем в непосредственно AST
                                                                                                  Ответить
                                                                                                  • > Какая-нибудь лямбда может записываться как-нибудь так например:
                                                                                                    И даже так семантику происходящего ты никак ня узнаешь. Что эта лямбда делает с переменными, что можно с ней делать, какие някладные расходы у её создания, какие побочные эффекты — совершенно ня ясно. Она тебе может скобочки перегрузить, а ты и ня узнаешь.

                                                                                                    > Тут всё завист от конкретики, как эта работа с AST реализована, каков изначальный синтаксис и система типов в конкретном ЯП, насколько интуитивно синтаксис отображаем в непосредственно AST
                                                                                                    Дело не в интуитивности, дело в семантике. Прямое управление AST нужно только для одного: для горожения собственных DSLей, для изменения семантики языка.
                                                                                                    Ответить
                                                                                                    • > Что эта лямбда делает с переменными, что можно с ней делать, какие някладные расходы у её создания, какие побочные эффекты — совершенно ня ясно. Она тебе может скобочки перегрузить, а ты и ня узнаешь.

                                                                                                      Для этого есть документация или сам код металибы на худой конец.

                                                                                                      > Дело не в интуитивности, дело в семантике.

                                                                                                      Ну так если у меня AST близок к синтаксису (s-expr как в лиспах), и у меня есть металиба, которая имеет права на чтения всей единицы трансляции, а конструировать AST фигню она допустим может только лишь в особо огороженных предварительно прописанных областях, то можно просто посмотреть, во что конкретно такая-то лямбда развернется вот там-то и там-то. А если язык с синтаксисом как в крестах с какими-то [](){}<blabla<kokok{}<kukarek> > то хрен там плавал
                                                                                                      Ответить
                                                                                                      • > и у меня есть металиба, которая имеет права на чтения всей единицы трансляции, а конструировать AST фигню она допустим может только лишь в особо огороженных предварительно прописанных областях
                                                                                                        Ну да, и так мы получаем ограниченное управление AST, о чём я и говорила изнячально. Опять же, что-то похожее, но ещё чуть-чуть более ограниченное, предлагает Саттер в своих метаклассах.
                                                                                                        Ответить
                                                                                                    • > Дело не в интуитивности, дело в семантике. Прямое управление AST нужно только для одного: для горожения собственных DSLей, для изменения семантики языка.

                                                                                                      Что значит "изменения семантики?" Вот, к примеру, мой самый метушистый проект с прямым управлением AST: https://github.com/k32/typerefl

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

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

                                                                                                      Манипуляция AST даёт совсем другие возможности, нежели & в крестах перегружать. Вот пилить DSL на крестах с помощью перегрузок — это априори говно, тут соглашусь.
                                                                                                      Ответить
                                                                                                      • > Он никакие семантики не меняет, а добавляет некоторые фичи языку, которые иначе делались бы бойлерплейтом.
                                                                                                        И ты получаешь новый язык-нядмножество исходного, пони-мать который становится капельку сложнее. И чем больше таких фич добавляется — тем меньше готовый продукт становится похож на оригиняльный, что в пределе выливается в отдельный диалект (привет, Lisp!). А уж если AST можня крутить как угодня безо всяких ограничений, то дробление языка ня кусочки просто няизбежно.
                                                                                                        Ответить
                                                                                                        • > И ты получаешь новый язык-нядмножество исходного, пони-мать который становится капельку сложнее.

                                                                                                          Не понимаю наезда. Даже тупенькие джависты, которые боятся перегрузок, ибо сложна, ничего не понятно, используют аннотации. Тут тоже самое: видишь аннотацию, понимаешь, что она превращается в такую-то фигню.

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

                                                                                                          Дробление языка на кусочки прекрасно делается и без помощи трансформации AST. Достаточно заиметь две либы, использующие разные имплементации строк. (Привет, haskell, с пятью типами строк)
                                                                                                          Ответить
                                                                                                          • В теории, конечно, можно запилить parse_transform, который все строковые литералы заменяет на цитаты из зелёного слоника, но тут, как и везде, нужно использовать здравый смысл.

                                                                                                            Кстати, хорошая идея, надо запилить.
                                                                                                            Ответить
                                                                                                            • > но тут, как и везде, нужно использовать здравый смысл.
                                                                                                              Проблема в том, что все либы пишут дураки разной степени дурашливости — причём как субъективно, так и объективня. Поэтому ЯП общего нязначения (в отличие от нямеренно элитарных, вроде того же Хаскелля) обязаны соблюдать баланс: они должны, с одной стороны, достаточно ограничивать дураков, чтобы они ня начли творить беспредел, а с другой — давать достаточня возможностей творить беспредел тогда, когда он будет уместен.

                                                                                                              > В теории, конечно, можно запилить parse_transform, который все строковые литералы заменяет на цитаты из зелёного слоника
                                                                                                              На няфицированные цитаты из Зелёняго Слоняка!
                                                                                                              Ответить
                                                                                                              • POC (не оптимизировал)
                                                                                                                -module(green_elephant).
                                                                                                                
                                                                                                                -export([parse_transform/2]).
                                                                                                                
                                                                                                                parse_transform(Forms, _Options) ->
                                                                                                                  traverse(Forms).
                                                                                                                
                                                                                                                traverse({string, Line, Str0}) ->
                                                                                                                  Str = nyaify(bratishkify(Str0)),
                                                                                                                  {string, Line, Str};
                                                                                                                traverse(L) when is_list(L) ->
                                                                                                                  lists:map(fun traverse/1, L);
                                                                                                                traverse(T) when is_tuple(T) ->
                                                                                                                  list_to_tuple(lists:map(fun traverse/1, tuple_to_list(T)));
                                                                                                                traverse(T) ->
                                                                                                                  T.
                                                                                                                
                                                                                                                nyaify(S) ->
                                                                                                                  re:replace(S, "на", "ня", [{return, list} | re_opts()]).
                                                                                                                
                                                                                                                bratishkify(S) ->
                                                                                                                  re:replace(S, "[eE]rror", "НАЧАЛЬНИК, ЭТОТ ПИДОРАС ОБОСРАЛСЯ!!!", re_opts()).
                                                                                                                
                                                                                                                re_opts() ->
                                                                                                                  [global, unicode, caseless].


                                                                                                                Применяем к коду:

                                                                                                                -module(main).
                                                                                                                
                                                                                                                -export([main/1]).
                                                                                                                
                                                                                                                -compile({parse_transform, green_elephant}).
                                                                                                                
                                                                                                                main(_Opts) ->
                                                                                                                  io:setopts([{encoding, unicode}]),
                                                                                                                  io:format("Error: ~p~n", [foo]).

                                                                                                                Выводит
                                                                                                                няЧАЛЬНИК, ЭТОТ ПИДОРАС ОБОСРАЛСЯ!!!: foo
                                                                                                                Ответить
                                                                                                                • P.S. Версия 2.0.

                                                                                                                  -module(green_elephant).
                                                                                                                  
                                                                                                                  -export([parse_transform/2]).
                                                                                                                  
                                                                                                                  parse_transform(Forms, _Options) ->
                                                                                                                    case erlang:localtime() of
                                                                                                                      {{_Year, 12, 31}, {Hour, _, _}} when Hour > 20 ->
                                                                                                                        traverse(Forms);
                                                                                                                      _ ->
                                                                                                                        Forms
                                                                                                                    end.
                                                                                                                  
                                                                                                                  traverse({string, Line, Str0}) ->
                                                                                                                    Str = re:replace(Str0, "(\\p{Xsp}|^)\\p{L}+", "\\1курлык", [global, unicode, {return, list}]),
                                                                                                                    {string, Line, Str};
                                                                                                                  traverse(L) when is_list(L) ->
                                                                                                                    lists:map(fun traverse/1, L);
                                                                                                                  traverse(T) when is_tuple(T) ->
                                                                                                                    list_to_tuple(lists:map(fun traverse/1, tuple_to_list(T)));
                                                                                                                  traverse(T) ->
                                                                                                                    T.
                                                                                                                  Ответить
                                                                                                          • > Даже тупенькие джависты, которые боятся перегрузок, ибо сложна, ничего не понятно, используют аннотации.
                                                                                                            Ну да, я об этом и пишу: чем сильнее метушня ограничена — тем меньше от неё вреда.
                                                                                                            Возможность управления AST можно сравнить с няявными преобразованиями типов: когда их слишком мало — получается унылый бойлерплейт "foo(intVar.toLong())", когда их слишком много — получается 16 + "JavaScript".
                                                                                                            Хорошо, когда AST можно дёргать чуть-чуть: это избавляет от бойлерплейта. Плохо, когда AST можно дёргать как угодно, и подключённая металиба перегружает тебе пробелы.

                                                                                                            > Достаточно заиметь две либы, использующие разные имплементации строк.
                                                                                                            Да, строки лучше иметь в стандартной библиотеке. Вот бы они в C++ были...
                                                                                                            Ответить
                                                                                                            • > Ну да, я об этом и пишу: чем сильнее метушня ограничена — тем меньше от неё вреда.

                                                                                                              Так-то можно сделать ограниченную метушню из неограниченной, и пользоваться этой ограниченной метушней. К неограниченной метушне прибегать только в случае крайней на то необходимости, соблюдая все меры предосторожности. Если какие-то дураки будут неограниченную метушню использовать по поводу и без, это уже их личные проблемы, в условиях свободной конкуренции их кривыми говнометалибами пользоваться не будут и их говнометушня канет в лету.
                                                                                                              Ответить
                                                                                                              • > в условиях свободной конкуренции их кривыми говнометалибами пользоваться не будут и их говнометушня канет в лету.
                                                                                                                В условиях свободной конкуренции PHP стабильня входит в топ-10 самых популярных языков программирования. C++, кстати, тоже.
                                                                                                                А личные проблемы дураков в один прекрасный момент внязапно станут твоими проблемами, когда тебе вдруг понядобится специфическая либа или поддержать чужой проект.

                                                                                                                Нят, в принципе, если все свои проекты ты пишешь в одиночку и никогда чужой код ня читаешь — то такой образ мышления вполне себе работает.
                                                                                                                Ответить
                                                                                                                • > В условиях свободной конкуренции PHP стабильня входит в топ-10 самых популярных языков программирования. C++, кстати, тоже.

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

                                                                                                                  Если б C++ появился одновременно с появлением Rust, и при этом не было б никакого языка Си, который достаточно с крестами совместим (т.е. если б C++ был вообще с нуля придуман, и нельзя было сишкокод переиспользовать) то что-то я сомневаюсь, что кресты б выиграли в этой конкуренции.
                                                                                                                  Ответить
                                                                                                • > Разница в том, что "обычная" либа не изме-ня-ет сам язык. Какую бы ты крестолибу ня взял — const у тебя останется модификатором константности, шаблоны будут объявляться через template<...>

                                                                                                  Можно сделать некие правила, ограничивающие область работы металибы вот таким-то участком кода (скоупом функции, или вообще условием внутри некоего цикла, если удобно), ну типа

                                                                                                  for (int i = 0; %%USE_METALIB1%%{someshit};%%USE_METALIB2%%{someshit2})
                                                                                                  Ответить
                                                                                                  • > ограничивающие
                                                                                                    Ну да, а потом придёт k234234 и начнёт утверждать, что это анскильно, дайте мне возможность перегрузить пробел во всём TU.
                                                                                                    В пропозале с метаклассами, кстати, специально выделено (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0707r4.pdf):
                                                                                                    5.2 Q: Will this encourage dialects and fragmentation, as with Lisp
                                                                                                    and Smalltalk? A: No.
                                                                                                    Unlike Lisp and/or Smalltalk facilities, metaclasses cannot:
                                                                                                    • redefine language facilities;
                                                                                                    • redefine other people’s types; or
                                                                                                    • affect the global environment.
                                                                                                    
                                                                                                    Metaclasses are just a convenient way to write your own type(s),
                                                                                                    with exactly the same capabilities C++ already
                                                                                                    has if you write exactly the equivalent type out longhand
                                                                                                    without the metaclass.

                                                                                                    Саттер всё предусмотрел.
                                                                                                    Ответить
                                                                                                    • Ну и, кстати, весь параграф "Problems in other languages" там — это как раз всё то, о чём я пытаюсь няписать.
                                                                                                      Ответить
                                                                                                    • > Ну да, а потом придёт k234234 и начнёт утверждать, что это анскильно, дайте мне возможность перегрузить пробел во всём TU.

                                                                                                      Ну так всю TU завернуть в %%USE_METALIB1%% можно, но если чего-то не так будет, это уже твои проблемы. И да, если к некоторому куску кода применять более одной металибы, то порядок может иметь значение. Например если одна либа заменяет пробелы на запятые, а другая заменяет запятые на пробелы, а в коде есть и пробелы, и запятые.
                                                                                                      Ответить
                                                                                    • И да, почему б не запретить в крестах шаблонное метапрограммирование? Там ведь тоже можно своих говновелосипедов понаделывать, и будет очень много вреда.
                                                                                      Ответить
                                                                                      • Удивительня, но Комитет действительно делает слабые подвижки в этом няправлении*: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html
                                                                                        2118. Stateful metaprogramming via friend injection
                                                                                        Section: _N4868_.13.8.6  [temp.inject]    
                                                                                        Status: open    
                                                                                        Submitter: Richard Smith    
                                                                                        Date: 2015-04-27
                                                                                        
                                                                                        Defining a friend function in a template, then referencing that function later
                                                                                        provides a means of capturing and retrieving metaprogramming state.
                                                                                        This technique is arcane and should be made ill-formed.
                                                                                        
                                                                                        Notes from the May, 2015 meeting:
                                                                                        
                                                                                        CWG agreed that such techniques should be ill-formed, although the mechanism
                                                                                        for prohibiting them is as yet undetermined.

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

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


                                                                                        * Правда, понять, как пофиксить эту дыру, они пока что ня смогли.
                                                                                        Ответить
                                                                                • В реальном мире Domain Specific Languages — удел либо развлекательного программирования, либо фанатиков, не видящих дальше своего крошечного мирка.
                                                                                  Ответить
                                                                                  • Имення так, сестрёнка! DSL — это идеальный способ нявечно прикрутить проект к трём с половиной спецам, умеющих/готовых этот DSL готовить. Впрочем, если в целевой отрасли кроме этих трёх с половиной спецов больше някого и нет — тогда всё нормальня.
                                                                                    Ответить
                                                                                    • То же крестошаблонное метапрограммирование - тоже DSL, только (в сравнении с лиспом) кривое и крайне ограниченное. Зато стандартное.
                                                                                      Ответить
                                                                                  • Выкатил в кровавый прод 3 DSL своего сочинения, не нядо. Один был на ЙАЖА, лол. Но про это мы не вспоминаем.
                                                                                    Ответить
                                                                            • > Лучше выучить один стандартный сахарок и везде использовать его, чем зубрить двадцать самописных сахарков, решающих одно и то же, но по-разному и с кучей неочевидных нюансов каждый.

                                                                              Стандартного сахарка может быть мало, а когда (если) комитет разродится стандартом, где появится нужный тебе здесь и сейчас сахарок, ты уже можешь сменить работу и даже уйти на пенсию.
                                                                              Ответить
                                                                              • Вме-ня-емые люди при отсутствии сахара просто пишут без сахара. Сахар — это просто по определению то, что можно сделать руками, просто с сахаром быстрее и проще.
                                                                                Ответить
                                                                  • Ну и няпоследок:
                                                                    auto lambda = [&] { /* */ };

                                                                    Захвачены будут только те переменные, которые упомянуты в теле. Ручной же эмуляции всё равно придётся прописывать весь бойлерплейт и своевременно обнявлять его.
                                                                    Ответить
                                                          • Да, а потом вот так:
                                                            ENTITY_EVENT_SPECIALIZATION(EV_CLIENTJOIN)
                                                                {
                                                                    using ENTITY_EVENT_DEFAULT_CONSTRUCTOR;
                                                                    ENTITY_EVENT_PARAM_GETTER(getClientNum);
                                                                };

                                                            Коротко, красиво, ясно, УДОБНО.

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

                                Это классический баг программиста, я вижу его постоянно, он называется "не решает всех проблем".

                                Некто пользуется инструментом $FOO.

                                Ему говорят: инструмент $BAR позволяет делать тоже самое, но писать при этом меньше кода

                                Некто отвечает: но $BAR ведь тоже не решает всех проблем, так что $BAR не нужен.

                                Примеры:

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

                                "ORM не решает всех проблем, иногда нужно писать SQL вручную, следовательно ORM не нужен"

                                итд
                                Ответить
                                • Стандартная защитная реакция психики: я не хочу учить ничего нового (стандартное желание человека: мы эволюционно склонны к экономии энергии), но ня хотят учиться только ленивые-глупые-плохие люди*, поэтому, чтобы не прослыть в глазах других ленивым-глупым-плохим, я объявлю $BAR плохим. Разумеется, происходит всё это полностью нясознательно.

                                  *Это, конечно, ня так.
                                  Ответить
                                  • >Стандартная защитная реакция психики: я не хочу учить ничего нового

                                    Изучение Крестостандарта — главная ценность в мире крестоблядей. Твой вес в этом обществе определяется не размером счета в банке, а тем, насколько ты продвинут в знании Крестоговна.
                                    Ответить
                                    • Изучение колдовства — главная ценность в мире магоблядей. Твой вес в этом обществе определяется не размером счета в банке, а тем, насколько ты продвинут в знании заклинаний.
                                      Ответить
                                    • C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений.
                                      Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист.
                                      Умение героически преодолевать трудности, которые создает твой собственный инструмент, вместо того, чтобы решать непосредственно прикладную задачу, в современном мире ценится разве что только среди прыщавых сосок.
                                      Работодатель же это сомнительное умение не ценит, и совершенно справедливо.
                                      Ответить
                                      • это было сказано до с++11 к слову

                                        высказываний vsl про modern c++ к сожалению не сохранилось
                                        Ответить
                                      • Всё так. Поэтому когда в C++ появляется что-то реально удобное и облегчающее жизнь — сразу нябегают хорошие зубрилки и нячинают объяснять, почему оно ня нужно.
                                        Ответить
                          • > Так что надо эти мувы делать именно при возврате, а не вот просто сразу.
                            Пожалуйста:
                            void use_callback(const std::function<void()> & callback)
                            {
                                std::cout << "use_callback(): ";
                                callback();
                            }
                            
                            auto get_callback(std::string name)
                            {
                                auto msg = "Hello, " + std::move(name);
                            
                                // В этой лямбде вся бизнес-логика с msg
                                auto lambda = [](const auto & msg) {
                                    std::cout << "lambda: " << msg << std::endl;
                                };
                            
                                // Эти лямбды передаются по ссылке и по ссылке же трогают msg
                                use_callback([&msg, &lambda] { lambda(msg); });
                                use_callback([&msg, &lambda] { lambda(msg); });
                                use_callback([&msg, &lambda] { lambda(msg); });
                            
                                std::cout << "get_callback(): msg == " << msg << std::endl;
                            
                                // Эта лямбда уносит msg с собой
                                return [msg = std::move(msg), lambda] {
                                    lambda(msg);
                                };
                            }
                            
                            int main()
                            {
                                auto callback = get_callback("World");
                                std::cout << "main(): ";
                                callback();
                            }

                            https://wandbox.org/permlink/qXV0Y5ryFQIO1WAx

                            > Референс каунтер, коим этот shared_ptr является - уже анскильно и попахивает GC.
                            Вам шашечки или ехать?

                            > то это всё будет через стек копироваться, да?
                            Что "всё"? msg — это, грубо говоря, size_t и указатель. Да, size_t и указатель будут копироваться через стек.

                            > А если ту лямбду в глобальную std::function присвоить, где будет храниться ее msg?
                            Детали реализации, нясколько я знаю. Но std::function — сама по себе крайне тяжёлая, в контексте подсчёта байтиков её использовать страння.
                            Ответить
                            • > Что "всё"? msg — это, грубо говоря, size_t и указатель. Да, size_t и указатель будут копироваться через стек.

                              Переменных может быть и побольше. Но так-то да, все переменные можно выделить в одном аллоцированном куске памяти в хипе и просто таскать указатель на этот хип, и при возврате лямбды через return просто пробрасывать этот указатель.
                              Ответить
                              • Ага.
                                auto get_callback(std::string name)
                                {
                                    struct Locals {
                                        int a;
                                        float b;
                                        std::string c;
                                    };
                                    auto locals = std::make_unique<Locals>();
                                
                                    locals->c = std::move(name);
                                    locals->a = 16;
                                    locals->b = locals->c.size() / static_cast<float>(locals->c.capacity());
                                
                                    // locals — один указатель
                                    return [locals = std::move(locals)] { 
                                        std::cout << "a = " << locals->a << std::endl
                                                  << "b = " << locals->b << std::endl
                                                  << "c = " << locals->c << std::endl;
                                    };
                                }
                                
                                int main()
                                {
                                    auto callback = get_callback("World");
                                    callback();
                                }
                                Ответить
                                • Дополнительные очки упоротости за собственный аллокатор для систем без кучи.
                                  Ответить
                • Проблема гомоиконности данных и кода. Помню писал говнореализацию говнофункционального говноязыка, и нарвался на то что у меня рекурсия в моей программе была в терминах интерпретатора тоже рекурсией, стек переполнялся в леккую, мне ещё кашицын объяснял, что надо аст развернуть и всю рекурсию заменять циклом.
                  Ответить
                • Кстати ты еще через mmap() выделить память с правами rw-, понабрасывать туда опкодов, потом через mprotect() поменять на r-w и вызывать эту срань как функцию, но mmap и mprotect в стандарте Си нет, в винде есть аналоги этой хуйни естественно.
                  Ответить
          • Определение функции по месту в 90% нужно, когда ты эту функцию суёшь в другую функцию, т.е. работаешь с функциями высшего порядка. Т.е. заигрываешь с ФП. Когда ты пользуешься функцией высшего порядка, ты на время отдаёшь ей контроль. Завязывать логику на то, что именно внутри этого чёрного ящика происходит, не comme-il-faut.
            Ответить
            • Ну в сишке можно указатели на функции передавать. Ничто не мешает написать функцию, которая получает в качестве аргумента другую функцию.

              Просто это корявенько.

              Причем в сишке это можно делать 50 лет как, а в котором мейнстим говне (не будет показывать на джаву пальцем) это добавили совсем недавно (до этого эмулировалось через классы)
              Ответить
              • > Ну в сишке можно указатели на функции передавать.

                А в фортране ASSIGNED GO TO есть. Вместо указателя на функцию можно номер строчки передавать ^___~

                > (до этого эмулировалось через классы)

                Там и сейчас, вроде, нормального стрелочного типа нет, вместо него инстансы Function генерятся.
                Ответить
                • > А в фортране ASSIGNED GO TO есть. Вместо указателя на функцию можно номер строчки передавать ^___~

                  В GNU C есть такое расширение, и у меня про него говнокод был примерно 5 лет назад https://govnokod.ru/19105
                  Ответить
  • Я вспомнила, что мне вся эта дискуссия няпоминает!
    Купили как-то суровым сибирским лесорубам японскую бензопилу.
    Собрались в кружок лесорубы, решили ее испытать.
    Завели ее, подсунули ей деревце.
    «Вжик» — сказала японская пила.
    «У, ня...» — сказали лесорубы.
    Подсунули ей деревце потолще. «Вж-ж-жик!» — сказала пила.
    «Ух, ня!» — сказали лесорубы.
    Подсунули ей толстенный кедр. «ВЖ-Ж-Ж-Ж-Ж-Ж-Ж-ЖИК!!!» — сказала пила.
    «Ух ты, ня!!» — сказали лесорубы.
    Подсунули ей железный лом. «КРЯК!» — сказала пила.
    «Ага, ня!!!» — укоризненно сказали суровые сибирские лесорубы! И ушли рубить лес топорами…
    Ответить

Добавить комментарий

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8