1. Си / Говнокод #25456

    +5

    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
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    /*
    https://habr.com/ru/company/jugru/blog/444212/
    
    Александр: Я не думаю, что существует какое-то одно «правильное» определение ФП,
    но если говорить лично обо мне, то ФП — это нечто с функциональной композицией и
    функциями первого класса.
    
    Иван: Я согласен, но добавил бы ещё функции высшего порядка — те, которые могут
    принимать другие функции в качестве аргументов и возвращать как результат.
    
    Cергей: Ссылка на функцию в Си — считается?
    
    Иван: Нет, Си не является функциональным языком программирования :-)
    
    Сергей: Расскажи, почему?
    
    Иван: Потому что нельзя из комбинации указателей на функции создать новую функцию,
    можно только указывать на уже существующие. Конечно, если в ход не пошли какие-то
    ассемблерные хаки.
    */
    
    
    #include <stdio.h>
    #include <inttypes.h>
    #include <stddef.h>
    #include <stdlib.h>
    #include <errno.h>
    
    #define FUNC(a, ...) typeof( a (*) (__VA_ARGS__) )
    
    uint64_t mul2(uint64_t a)
    {
      return a*2;
    }
    
    uint64_t add2(uint64_t a)
    {
      return a+2;
    }
    
    uint64_t chaincaller(uint64_t a, typeof(uint64_t (*)(uint64_t)) *chain)
    {
      while(*chain != NULL)
      {
        a = (*chain)(a);
        chain++;
      }
      return a;
    }
    
    FUNC(uint64_t, uint64_t) *combine_fn (FUNC(uint64_t, uint64_t) a, FUNC(uint64_t, uint64_t) b)
    {
      FUNC(uint64_t, uint64_t) *funchain = (FUNC(uint64_t, uint64_t) *)malloc(sizeof( FUNC(uint64_t, uint64_t) [3]) );
      if (funchain == NULL)
      {
        exit(ENOMEM);
      }
      funchain[0] = a;
      funchain[1] = b;
      funchain[2] = NULL;
      return funchain;
    }
    
    
    int main(void)
    {
      FUNC(uint64_t, uint64_t) *func_chain = combine_fn(mul2,add2);
      uint64_t a = 15;
      uint64_t b = chaincaller(a, func_chain);
      printf("%" PRIu64 " * 2 + 2 = %" PRIu64 "\n", a,b);
      free(func_chain);
      return 0;
    }

    Ассемблерные хуяки.
    https://wandbox.org/permlink/gdRggB77GQOiNzyJ
    Он так говорит, будто б в крестоговно впилили какой-то недоJIT, который честно может сгенерить одну функцию из двух.

    Запостил: j123123, 19 Марта 2019

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

    • см. также: https://govnokod.ru/25009#comment436513
      Ответить
    • > Александр: Да, мне тоже нравятся лямбды — это фича настолько универсальная, что можно было бы писать только на них одних. Это что-то вроде универсального комбинатора, позволяющего конструировать любую логику — может, не так красиво, как в других языках, но не менее полезно.

      Ой бля... как всё запущено. Лямбда это просто синтаксический сахар, не более того. От этого нихуя не меняется. Можно вместо лямбд писать всякий раз новую функцию и ее вызывать в нужном месте.
      Ответить
      • показать все, что скрытоvanished
        Ответить
        • Ну тогда можно просто написать поебень в фигурных скобках
          int a = 5;
          a = [&]() {int b = 2; return a*b;}();
          printf("%d\n", a);
          
          // аналогично:
          int a = 5;
          {
            int b = 2;
            a = a*b;
          }
          printf("%d\n", a);


          Ну и не стоит забывать про расширения GCC https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
          int a = 5;
          a = ({int b = 2; a*b;})
          printf("%d\n", a);
          Ответить
          • Он наверное про замыкания, это ,конечно, тоже можно сделать, но с расширениями гцц типа трамплинов, или структуркой с контекстом, ну или особо ебанутые могут собрать лямду snprintf'ом, подставив в код аргументы, и потом mmap'нуть ))).
            Ответить
            • Это можно сделать при помощи «функторов».
              struct Functor {
                  Functor(int a, int b, int & c) :
                      captured_a(a),
                      captured_b(b),
                      captured_c(c)
                  {
                  }
              
                  int operator()(int arg1, int arg2)
                  {
                      captured_c = arg1 * arg2;
                      return captured_a + captured_b + arg1 + arg2;
                  }
              
              private:
                  int captured_a;
                  int captured_b;
                  int & captured_c;
              };
              
              int main()
              {
                  int a = 5,
                      b = 10,
                      c = 15;
                  Functor f(a, b, c);
              
                  std::cout << "f(3, 4) == " << f(7, 8) << std::endl;
                  std::cout << "c == " << c << std::endl;
              
                  return 0;
              }

              https://ideone.com/n8lmTk
              Собственно, до 11-х крестов так и делали. Да и сейчас лямбды — это обычный синтаксический сахар именно над такой «структуркой с контекстом». Ничего нового и революционного они в кресты не принесли, как бы фанатики из обсуждаемой статьи не вопили об обратном.
              Ответить
            • Да и «замыкания» из крестовых лямбд — откровенно дерьмовые.
              #include <iostream>
              #include <functional>
               
              struct X {
                  X(int arg = 1) :
                      someVar(arg)
                  {
                      std::cout << "X(" << arg << ")" << std::endl;
                  }
               
                  ~X()
                  {
                      std::cout << "~X(" << someVar << ")" << std::endl;
                  }
               
                  int someVar;
              };
               
              std::function<void()> get_lambda(int number)
              {
                  X x(number);
                  return [&x]() {
                      std::cout << "lambda from get_lambda: x.someVar == " << x.someVar << std::endl;
                  };
              }
               
              int main()
              {
                  auto lambda = get_lambda(42);
                  lambda();
               
                  return 0;
              }

              https://ideone.com/dNcjds
              Выходим из get_lambda(), x уничтожается, ссылка в лямбде протухает.

              В языках с нормальными замыканиями такой херни не происходит, потому что замыкание увеличивает срок жизни захваченных объектов, а вот в крестах это не прокатит по причине отсутствия GC (хотя, конечно, можно заюзать std::shared_ptr/unique_ptr — опять вручную).
              Ответить
    • > Александр: Я правильно понял, что множество топовых C++-разработчиков изучают Haskell только для того, чтобы понять, что творится с C++?

      > Иван: Не уверен, что они учат Haskell именно по этой причине. Думаю, C++-разработчики просто очень эгоистичные. Они так хорошо изучили C++ только потому, что он сложный. И если ты хочешь выучить что-то действительно новое, твой путь лежит явно не в какую-нибудь Java, которая специально создана быть простой. Тебе нужно искать в области необычных и странных языков, самых странных, и Haskell автоматически окажется среди самых популярных ответов. Человек видит его, понимает: о, это что-то более сложное, чем C++, нужно выучить. Когда я изучал Haskell, со мной было то же самое, и у меня есть знакомые, которые прошли точно по такой же цепочке рассуждений.

      Они так хорошо изучили C++ только потому, что он сложный.

      https://govnokod.ru/25343#comment456602 :
      > Хотя на самом деле это мастерство преодоление трудностей не нужно нормальному человеку, ибо здравомыслящий человек предпочитает избегать трудностей, а не героически преодолевать их, доказывая кому-то свою крутизну. Ну, это как если б кто-то жил в засранной квартире с кучей битого стекла и ржавых гвоздей торчащих из досок, и он поэтому научился ловко обходить битое слекло и гвозди, и потом среди таких же жителей засранных квартир он будет мегакрутым спецом. Но нормальный человек просто покрутит у виска и скажет, что навыки перепрыгивания через говно, гвозди и битое стекло нормальному человеку нахрен не нужны, и что он лучше будет жить в нормальной квартире, чем задрачивать навыки жизни в говне и потом выебываться этими навыками перед такими же долбоебами
      Ответить
      • > о, это более сложное
        Т.е. это как с наркотой - травка уже не вставляет, надо что-то более сильное?
        Ответить
      • показать все, что скрытоvanished
        Ответить
        • Я такой грустный - потому что ваш гуй не вкусный
          Ответить
          • Вы просто не умеете его употреблять!
            Думаете, консоль вкуснее?
            Наш гуй –— самый лучший изо всех, которые были.
            Все умные люди пользуются нашим гуём!
            Зато нашим гуём не смогут воспользоваться пиндосы!
            Если не наш гуй, то что?
            У вас бы на нашем месте тоже был бы невкусный гуй.
            Не врите, наш гуй вкусный: двоюродной сестре третьей жены брата маминого внучатого племянника всё понравилось!
            Ответить
      • Вы просто не умеете перепрыгивать через гвозди и через говно, вот и беситесь!

        «C++» –— самый лучший ЯП изо всех, которые были.
        «C++» –— единственный ЯП, за который не стыдно.
        Если не «C++», то что?
        «С++» –— мировой лидер среди ЯП.
        Все умные люди пишут на «C++».
        Язык «C++» поднял программирование на новый уровень.
        «С++» напугал любителей абаков и логарифмических линеек.
        Благодаря «С++», всё в ПО изменилось в лучшую сторону.

        А какая основа «C++» после сишки досталась!
        Думаете, легко изобретать стандарты для такого популярного ЯП, как «С++»?
        Комитет не может уследить за всеми мелочами.
        Дайте комитету ему время!
        Комитету враги мешают.
        Комитет отвечает только за синтаксис, за реализацию отвечают производители компиляторов, так что в багах компиляторов комитет не виноват.

        В «BCPL» было хуже!
        В любом ПО большая часть написана на «C++»!
        Вы бы на месте Страуструпа тоже хуйни наворотили!
        Не врите, в «C++» всё легко: у двоюродной сестры третьей жены брата маминого внучатого племянника всё получается!
        Кто работал и не ленился, тот научился перепрыгивать через гвозди и через говно!
        ПО на «C++» полно, кто хочет, тот справляется.
        В «Malbolge» разве лучше?
        Такие проблемы есть везде, а не только в «C++».
        Надо работать, а не ныть!
        Зато в «C++» нет программистов «по случаю»!

        Кто ты такой, чтобы критиковать «С++»?
        Начни с себя! Изобрети полезный ЯП!
        Вы прогнулись под «Паскаль»/«Жабу»/«C#»/«PHP»!
        За что ты так ненавидишь программирование?
        Не нравится «C++» –— переходи на «PHP», никто не держит!
        Ответить
      • Да уж, феерическое выступление. Прямо какой-то клуб мазохистов-фанатиков (ещё и в теме не разбирающихся, судя по посту).
        Ответить
      • >Я правильно понял, что множество топовых C++-разработчиков изучают Haskell только для того, чтобы понять, что творится с C++?

        Ахахаха.
        Сказочные функциональщики!

        Спасибо. Связь хачкеля и крестов confirmed.
        Ответить
    • Во всей функциональщине, включая крестоблядскую, вместе с функцией тащат указатель на некий контекст.

      Если в сишке рассматривать пары из указателя на функцию и контекста, то такое подмножество сишки, внезапно, становится полноценным функциональным языком. Вот и вся магия.
      Ответить
      • >вместе с функцией тащат указатель на некий контекст

        Угу. В «ооп» эту роль выполняет неявный this. Иногда под капотом он превращается в первый аргумент метода. Иногда (js) подчиняется своду из десятка правил.

        И ещё непонятно чего от такой сахарной магии больше: пользы или вреда.
        Ответить
    • показать все, что скрытоvanished
      Ответить
      • Хорошо, что свадебное платье и хрустальные туфельки не подарил. Ебануться просто.
        Ответить
    • Вообще я не очень-то понимаю. Что такого от ФП в плюсах? Раскрытие говношаблонов? Так это просто какая-то компилтайм-питушня. В самом языке (ну т.е. в рантайм-поебени) никакого ФП нет. Лямбды это просто синтаксический сахар, который вообще нихуя не меняет. Не, можно конечно в функциональном стиле писать, типа иммутабельные массивы делать, и при изменении какого-то говна в этом массиве мы будем создавать новый иммутабельный, блядь, массив (и похуй что это медленно!!) с измененными данными, а старый удалять (чтоб функциональненько!), всегда возвращать какое-то говно через return вместо передачи по ссылке и изменения этого говна (мутабельность плохо, понятненько?).
      Вообще, херня какая-то. Называть такую поебень функциональщиной это как сказать что у меня в туалете установлено биде, ведь когда большие куски дерьма падают в воду, брызги оттуда попадают мне на жопу.
      Ответить

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