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

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  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 PolinaAksenova, (Updated )

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

      • Так точня (≧◡≦)!
        Хотя, справедливости ради, ответы ня нястоящем 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
                Ответить
          • ломбок пишется отдельно, а внутри кода меты нету
            Ответить
      • Меня заебала метушня на говнокоде. Сам я её не пешу.
        Ответить
        • не верю, что ты никогда не используешь шаблоны

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

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

Переведи на "PHP", guest!

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


    8