1. C++ / Говнокод #27340

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    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, 06 Апреля 2021

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

    • а что больше никому не интересно компиляторо писание :)?
      Ответить
      • Ты просто забыл сделать SEO пост. Все смотрят на сток, а новые говнокоды без комментов в нём не появляются.
        Ответить
    • intent надо было глобалкой сделать, чтобы наверняка.
      Ответить
      • P.S. Наверно всё-таки you intended indent rather than intent
        Ответить
        • Learning English is difficult, but it can be taught through tough thorough thought though
          Ответить
        • да мое знание инглиш ограничены умственными способностями поэтому пишу intent в отличии от indent
          Ответить
          • Английкий нужно изучать
            https://img.gazeta.ru/files3/32/13548032/gayduck-pic905-895x505-71993.jpg
            Ответить
            • > Gayduck

              Мой любимый поисковик :-)
              Ответить
              • Рэнди развивает интерес к соседскому сараю, пукает и продолжает тем, что наносит вербальные оскорбления соседу (а также пролетавшему мимо вертолёту). Затем сосед признаёт, что он — «однорукий уткоёб» («one-armed duck-fucker»).
                Ответить
            • ♫От стыда не красней.♫
              ♫Утка-гей, утка-гей.♫
              Ответить
      • а че такое. мне и так нравиться... или зачем придумали лямбду в с++?
        Ответить
        • Лямду придумали, чтобы функциональщина. Только лямда курильщика захваченные переменные мутирует
          Ответить
          • > мутирует

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

              Если 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 и такое можно)
                          Ответить
                          • Так в 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, а на что нет.
                                                      Ответить
                                                      • Лучше уж ассемблер. Там даже переменных как таковых нет, есть только регистры и память.
                                                        Ответить
                                                        • стек же есть, во всяком случае в x86
                                                          Ответить
                                                          • На 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());                                    \
                                                                  }

                                                              — как видишь, все эти ваши хвалёные метаклассы прекрасня эмулируются старым добрым препроцессором, а, следовательня, не нужны.
                                                              Ответить
                                                              • Препроцессором ты AST не модифицируешь
                                                                Ответить
                                                                • И что? Что концептуально нового добавляют в язык метаклассы — что без них нельзя сделать ручками/препроцессором?
                                                                  Ответить
                                                                  • Если ставить вопрос таким боком, концептуально нового и сишка с ассемблером не добавляет. Можно упороться и всю программу вместе с 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() и изменить определение. Аналогичня — для всех остальных переменных.

                                                                      Все эти проблемы крестовая лямбда эффективно решает: забыть инициализировать ничего нельзя, список захвата пишешь ровно один раз, все типы выводятся автоматически, способ захват чётко и ясно виден ровно в одном месте, и, что важно, прямо перед определением тела функции.
                                                                      Ответить
                                                                      • Polina самая лучшая сестричка-крестовичка, ня!
                                                                        ~ \{=^~^=}/ ~
                                                                        Ответить
                                                                      • // тут набросаем локалок
                                                                        #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) с полным по-Тьюригну языком для компилтайм-конструирования хреней, и можно эту лямбдию легко реализовать без каких-либо особенных затрат. И на такой хрени можно бы было делать реально мощные вещи, а не только какие-то лямбды.
                                                                            Ответить
                                                                            • А что, если создатели языков программирования не хотят, чтобы что-то подобное появилось? Потому что тогда все остальные языки не будут нужны, и программисты станут метапрограммистами...
                                                                              Ответить
                                                                              • > А что, если создатели языков программирования не хотят, чтобы что-то подобное появилось?

                                                                                А оно уже появилось.
                                                                                https://archive.jlongster.com/Lisp--It-s-Not-About-Macros,-It-s-About-Read

                                                                                > That should impress you. How would you do that in Python? Or Javascript? You need access to the AST and need to learn all the internal methods for parsing it. Lisp code is an 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 в стандарте Си нет, в винде есть аналоги этой хуйни естественно.
                    Ответить
                    • Да, наверное джиты так и работают?

                      Можно соснуть в openbsd с w^x, там вроде нельзя писать в страницу, а потом поменять ее на execute, если ты не слинковался со спец ключом, который тебе в заголовки ELF добавил запись типа "снять защиту"
                      Ответить
                      • >Да, наверное джиты так и работают?

                        Да, примерно так. Для ARM-ов надо еще какие-то кеши сбрасывать, а то можно огрести
                        https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/caches-and-self-modifying-code
                        Ответить
            • Определение функции по месту в 90% нужно, когда ты эту функцию суёшь в другую функцию, т.е. работаешь с функциями высшего порядка. Т.е. заигрываешь с ФП. Когда ты пользуешься функцией высшего порядка, ты на время отдаёшь ей контроль. Завязывать логику на то, что именно внутри этого чёрного ящика происходит, не comme-il-faut.
              Ответить
              • Ну в сишке можно указатели на функции передавать. Ничто не мешает написать функцию, которая получает в качестве аргумента другую функцию.

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

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

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

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

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

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

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