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

    +2

    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
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    template<typename F, typename... CurryArgs>
    struct curry {
        F func;
        std::tuple<CurryArgs...> tup{};
    
        curry(F f) : func(std::move(f)) {}
    
        template<typename... CtorArgs>
        curry(F f, CtorArgs &&... args) : func(std::move(f)), tup(std::forward<CtorArgs>(args)...) {}
    
        template<typename Tup1, typename Tup2>
        curry(F f, Tup1 && tup1, Tup2 && tup2) : func(std::move(f)), tup(std::tuple_cat(tup1, tup2)) {}
    
        template<typename... Args>
        auto operator()(Args &&... args)
        {
            constexpr size_t have_args = sizeof...(Args) + sizeof...(CurryArgs);
            constexpr size_t need_args = detail::functor_traits<F>::args_count;
            if constexpr (have_args > need_args) {
                static_assert(!sizeof(std::tuple_element_t<0, std::tuple<Args...>>*),
                              "Too many arguments.");
            } else if constexpr (have_args == need_args) {
                return std::apply(func, std::tuple_cat(tup, std::tuple(std::forward<Args>(args)...)));
            } else {
                return curry<decltype(func), CurryArgs..., Args...>(func, tup, std::tuple(std::forward<Args>(args)...));
            }
        }
    };
    
    int main()
    {
        auto f = [](int a, float b, const std::string & c) -> int {
            std::cout << "Functor! a = " << a << ", b = " << b << ", c = " << c << std::endl;
            return a + static_cast<int>(b);
        };
    
        std::cout << f(16, 42.1f, "Hello") << std::endl;
    
        auto c0 = curry(f);
        auto c1 = c0(16);
        auto c2 = c1(42.1f);
    
        c0(16)(42.1f)("Hello");
        c1(42.1f)("Hello");
        c2("Hello");
    
        c0(16, 42.1f)("Hello");
        c0(16, 42.1f, "Hello");
    
        c1(42.1f, "Hello");
    }

    Каррировали-каррировали, да выкаррировали.
    https://wandbox.org/permlink/LPXFUNpWOREcB3wH

    Запостил: PolinaAksenova, 10 Мая 2021

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

    • По мотивам https://github.com/type-challenges/type-challenges/blob/master/questions/462-extreme-currying-2/README.md ( ̄▽ ̄*)ゞ.
      Ответить
      • какой уродливый typescript
        Ответить
        • Так точня (≧◡≦)!
          Хотя, справедливости ради, ответы ня нястоящем TypeScript тоже ня блещут кавайностью:
          type AllArraySlices<T extends any[], Res extends any[] = []> = T extends []
            ? never
            : T extends [infer H, ...infer Rest]
              ? ([...Res, H] | AllArraySlices<Rest, [...Res, H]>)
              : never
          
          type AllArraySlicesTest1 = Expect<Equal<AllArraySlices<[1, 2, 3]>, [1] | [1, 2] | [1, 2, 3]>>
          type AllArraySlicesTest2 = Expect<Equal<AllArraySlices<[1, 2]>, [1] | [1, 2]>>
          
          type OmitFromFront<T extends any[], U extends any[]> = T extends []
            ? []
            : U extends []
              ? T
              : T extends [any, ...infer TRest]
                ? U extends [any, ...infer URest]
                  ? OmitFromFront<TRest, URest>
                  : never
                : never
          
          type OmitFromFrontTest1 = Expect<Equal<OmitFromFront<[1, 2, 3], [1, 2]>, [3]>>
          type OmitFromFrontTest2 = Expect<Equal<OmitFromFront<['a', 'b', 123, 555], ['a']>, ['b', 123, 555]>>
          
          type DynamicallyCurried<F extends (...args: any[]) => any> = <P extends AllArraySlices<Parameters<F>>>(...params: P) =>
            Parameters<F>['length'] extends P['length']
              ? ReturnType<F>
              : DynamicallyCurried<(...params: OmitFromFront<Parameters<F>, P>) => ReturnType<F>>
              
          declare function DynamicParamsCurrying<F extends (...args: any[]) => any>(fn: F): DynamicallyCurried<F>
          Ответить
    • Как обычно, горе-стандартизаторы нормального каррирования в кресты не завезли. Вот вам bind_front, вот вам apply, вот вам invoke, дальше ебитесь сами.
      Ответить
      • > bind_front
        А ведь всего-то оставалось в operator()() проверить количество аргументов и при нядостатке переконструировать эту фигню...

        Хотя для шаблонных функторов это бы ня сработало. Тогда насфинячить!
        Ответить
      • Каррировние были придумано математиками для того, чтобы уменьшить сложность формальных систем, бритвой Оккама убрав из них понятие "функции с многими аргументами".
        Поэтому совать его шаблонами в язык, где уже есть это понятие — бессмысленное занятие.
        По стечению обстоятельств, иногда каррирование ещё иногда позволяет писать компактный код с коллбеками. А иногда не позволяет. И тогда некоторые извращенцы продолжают писать в pointless-free стиле с flip, on, и т.д., от чего bind бы спас.
        Мораль: крестовички пусть юзают bind, и не бухтят, для их целей это более общий инструмент.
        Ответить
    • Заебала метушня уже. Как попугаи, блядь.
      Ответить
      • пиши на джаве, там метапрограммирования нет

        "распространен подход к выполнению большенства рутинных задач явно"
        Ответить
        • Лол, да там как раз дофига метушиной магии через аннотации.
          Ответить
          • Чтобы аннотации изменяли AST, нужно писать спец код.
            Так делают AspectJ (но джавистам велели его ругать, а приказы не обсуждаются) и NotNull аннотации JB

            А где там еще кокогенерация через аннотации?

            зы: ну ладно, лобок еще
            Ответить
            • Я не джавист, но AutoValue/AutoMatter, Mockito, в Guava вроде хватает метушни, через плечо видел.
              Ответить
              • Mockito умеет генерить классы по интерфейсу через cglib вроде, да

                Но это всё не такая метушня, как в крестах.

                В крестах я могу в уткину метушню: просто принимаю указатель на T, и вызываю у него метод foo().. в джаве я так могу разве что через рефлексию.

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

                Алсо, нужно думать, чтобы случайно не наинстанциировать 100500 одинаковых классов
                Ответить
                • > узнать об ошибке можно только по не очень внятным ошибкам компиляции

                  Именно поэтому и завезли концепты. Чтобы прогнать уток и вернуться к статической типизации.
                  Ответить
                  • Так это же только в 20, черт знает когда все это смогут...

                    У меня вот есть небольшой проект в 17-й студии, она вроде концептов не может
                    Ответить
                  • Так ведь концепты — это и есть полнейшая утка.
                    template<typename T>
                    concept Hashable = requires(T a) {
                        // Принимаем что угодня, для чего выражение в скобках convertible_to size_t
                        { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
                    };
                    Ответить
                • > Но это всё не такая метушня, как в крестах.

                  Как автор мема "метушня"[1], я определяю это слово как "мета-что-то". (Изначально это были метаданные в сетевом пакете, но также применимо к метапрограммированию). А кодогенерация — это она и есть, не важно на плюсошаблонах, макросах, TH, parse transforms, или printf'ом.

                  [1] https://govnokod.ru/20274#comment336929
                  Ответить
          • Это так. Тот же Ломбок нясилует https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html в хвост и в гриву, вертя байткодом как стрелкой осциллографа. От таких жутких хаков волосы ня хвосте дыбом встают {{ (>_<) }}!
            Ответить
            • ломбок пишется отдельно, а внутри кода меты нету
              Ответить
        • Меня заебала метушня на говнокоде. Сам я её не пешу.
          Ответить
          • не верю, что ты никогда не используешь шаблоны

            вся STL же на них
            Ответить
            • Пользоваться шаблонами != писать шаблоны. Это совсем разный уровень ёбли.
              Ответить
              • Ну какие-то совсем тупые шаблоны (уровня генериков) даже я писал, хотя я и не настоящий крестовик. Правда это не настоящая метушня, конечно
                Ответить
    • https://godbolt.org/z/bj8n6GY9n
      пиздец разпетушило.
      Ответить

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