1. Куча / Говнокод #27633

    +2

    1. 001
    2. 002
    3. 003
    4. 004
    5. 005
    6. 006
    7. 007
    8. 008
    9. 009
    10. 010
    11. 011
    12. 012
    13. 013
    14. 014
    15. 015
    16. 016
    17. 017
    18. 018
    19. 019
    20. 020
    21. 021
    22. 022
    23. 023
    24. 024
    25. 025
    26. 026
    27. 027
    28. 028
    29. 029
    30. 030
    31. 031
    32. 032
    33. 033
    34. 034
    35. 035
    36. 036
    37. 037
    38. 038
    39. 039
    40. 040
    41. 041
    42. 042
    43. 043
    44. 044
    45. 045
    46. 046
    47. 047
    48. 048
    49. 049
    50. 050
    51. 051
    52. 052
    53. 053
    54. 054
    55. 055
    56. 056
    57. 057
    58. 058
    59. 059
    60. 060
    61. 061
    62. 062
    63. 063
    64. 064
    65. 065
    66. 066
    67. 067
    68. 068
    69. 069
    70. 070
    71. 071
    72. 072
    73. 073
    74. 074
    75. 075
    76. 076
    77. 077
    78. 078
    79. 079
    80. 080
    81. 081
    82. 082
    83. 083
    84. 084
    85. 085
    86. 086
    87. 087
    88. 088
    89. 089
    90. 090
    91. 091
    92. 092
    93. 093
    94. 094
    95. 095
    96. 096
    97. 097
    98. 098
    99. 099
    100. 100
    // https://wandbox.org/permlink/rAilQ54oYBNsHJ3W
    
    struct blob_p(T,alias t_xmalloc,alias t_free)
    {
      blob!(T)* bl_p;
    
      size_t
      getlen
      (
      ) @trusted
      in
      {
        assert(bl_p != null);
      }
      do
      {
        return bl_p.len;
      }
    
      T*
      getdata
      (
      ) @trusted
      in
      {
        assert(this.bl_p != null);
      }
      do
      {
        return cast(T*)bl_p.data;
      }
    
    
      static bool
      cmp
      (
        typeof(this) a,
        typeof(this) b
      ) @trusted
      in
      {
        assert(a.bl_p != null);
        assert(b.bl_p != null);
      }
      do
      {
        if (a.bl_p.len != b.bl_p.len)
        {
          return false;
        }
        if(memcmp(cast(void*)a.bl_p.data, cast(void*)b.bl_p.data, a.bl_p.len * T.sizeof) != 0)
        {
          return false;
        }
        return true;
      }
    
      bool
      cmp
      (
        typeof(this) a
      ) @trusted
      in
      {
        assert(a.bl_p != null);
        assert(this.bl_p != null);
      }
      do
      {
        if (a.bl_p.len != this.bl_p.len)
        {
          return false;
        }
        if(memcmp(cast(void*)a.bl_p.data, cast(void*)bl_p.data, a.bl_p.len * T.sizeof) != 0)
        {
          return false;
        }
        return true;
      }
    
      T opIndex(size_t i)
      in
      {
        assert(bl_p != null);
        assert(bl_p.len > i);
      }
      do
      {
        return getdata()[i];
      }
    
      ~this()
      /*in
      {
        assert (cast(void*)bl_p != null);
      }
      do*/
      {
        t_free(cast(void*)bl_p);
      }

    Попробовал написать на "D" своего рода "массив" с известно каким размером

    Запостил: j123123, 31 Августа 2021

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

    • Только у меня "деструктор" с какого-то хуя два раза вызывается, один раз с null другой раз как надо. Почему?
      Ответить
      • Можно конструктор
        this
        (
          T[] arr ...
        )
        {
          this = blob_p(arr.length, arr.ptr);
        }

        переписать на
        this
        (
          T[] arr ...
        )
        {
          size_t len = arr.length;
          T *data = arr.ptr;
          bl_p = cast(typeof(bl_p))t_xmalloc(len.sizeof+len*T.sizeof); // тупо скопировать хуйню из blob_p(arr.length, arr.ptr);
          bl_p.len = len;
          memcpy(cast(void*)bl_p.data, cast(void*)data, len * T.sizeof);
        }

        И тогда норм.
        Но какого хрена там он решил вызывать деструктор, при таком вот "проксировании" конструктора? Как это сделать лучше?
        Ответить
        • А, там есть "делегирование конструктора" оказывается
          // https://dlang.org/spec/struct.html#delegating-constructor
            this
            (
              T[] arr ...
            )
            {
              this(arr.length, arr.ptr);
            }

          вот теперь норм. Всем спасибо за помощь )))

          Но вообще хуита, надо чтоб ГОМОИКОННОСТЬ
          Ответить
        • > Но какого хрена там он решил вызывать деструктор
          > при таком вот "проксировании" конструктора?
          > Как это сделать лучше?

          Переписать на «Си».
          Ответить
          • Да, надо будет сделать кококодогенерацию через printf(), отличная идея
            Ответить
            • Мне не нравится сама идея хранения длины вместе с указателем.

              Это какой паскализм и анскильная перепитушня.

              Часто размер массива известен в компайл-тайме. См. std::array.

              Зачем его вообще везде таскать?
              Ответить
              • А как лучше? Нуль-терминированные строки это анскилл потому что они коконкатенируются долго
                Ответить
                • > Нуль-терминированные строки это анскилл

                  Днище как бы не обсуждаем.

                  > А как лучше?

                  Говорю же, во многих случаях мне нравится использовать что-то вроде std::array<int16_t, 4> arr = {0, 1, 2, 3};
                  И размер не надо таскать. И превращается в mov rax, ...

                  Потому что всегда знаем в компайл-тайме, исходя из типа.

                  struct Arr{
                     int16_t a[4];
                  }
                  Есть одно неудобство : в Сишке нельзя написать
                  struct Arr<T, SIZE>{
                     int T[SIZE];
                  }

                  Ответить
                  • > Говорю же, во многих случаях мне нравится использовать что-то вроде std::array<int16_t, 4> arr = {0, 1, 2, 3};

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

                > Зачем его вообще везде таскать?

                Чтобы куда-то передать, если размер зависит от рантайм-хуиты.

                Тут длина хранится не вместе с указателем, а вместе с самими данными непосредственно, это как "flexible array member" - см. http://port70.net/~nsz/c/c99/n1256.html#6.7.2.1p16
                Ответить
                • > Тут длина хранится не вместе с указателем, а вместе с самими данными

                  А, ок.

                  Просто много пердолинга с конструкторами, деструкторами, assert(bl_p != null);

                  Этот синтаксиальный мусор напоминает джава-дрисню: геттеры, сеттеры, equals.

                  > EXAMPLE After the declaration:
                  > struct s { int n; double d[]; };

                  Кстати пример у них какой-то мудацкий.
                  Даже в моём говне размер size_t https://govnokod.ru/27633#comment667053
                  Ответить
      • > Только у меня "деструктор" с какого-то хуя два раза вызывается, один раз с null другой раз как надо. Почему?

        Возьми «Nim», там такой хуйни (деструкторов) нет.
        Ответить
        • Языки без деструкторов не нужны
          Ответить
          • Вообще-то я тебя обманул: стандартная библиотека «Nim» теперь реализована на так называемых «lifetime Hooks» и move-семантики, среди которых есть и «=destroy», это хук, который типа как деструктор.

            Как красиво и скилльно сделали, ах как же мне нравится мой любимый язык программирования «Nim»!
            Ответить
            • > это хук, который типа как деструктор

              Батюшка j123123 уже показывал как окрестить Сишку в RAII
              https://govnokod.ru/25526#comment471379

              https://wandbox.org/permlink/btXuxt1Gk3NENoxy
              Ответить
          • > Языки без деструкторов не нужны

            Языки с деструкторами не нужны.
            Ответить
            • Только няшная, только хардкор?
              Ответить
              • Нет. Почему же.

                В «JavaScript» никаких деструкторов нет. И живут же люди.

                Всё RAII можно заменить лямбдами.
                With (resource => {
                     resource.foo();
                })
                Только нужно научить говноязыки нормальному инлайну этих лямбд.
                Ответить
                • Ну не... такие лямбды -- это "raii" уровня джавы да питона. А дальше у ресурса вручную писать close() чтобы он закрыл подресурсы или за счёт рефлексии автоматом как-то обходить всё дерево и догадываться что закрыть?
                  Ответить
                  • > А дальше у ресурса вручную писать close() чтобы он закрыл подресурсы или за счёт рефлексии автоматом как-то догадываться что закрыть?

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

                    Реализация макроса With автоматически открывает ресурс и делает close/free.

                    Ответить
                    • Ну вот я не хочу ее туда собирать! Почему даже в сраных крестах я могу это не делать, а в джаве и её скриптах должна?
                      Ответить
                      • > даже в сраных крестах я могу это не делать

                        Это на словах в крестах всё просто и можно ничего не делать.

                        А в реальности нужно выучить пять десятков правил жизненного цикла объектов: конструкторов, деструкторов, присваиваний и ещё десяток исключений из этих правил.

                        Проще руками явно закрыть.
                        Ответить
                        • правила ты выучил за год, и потом десять лет программируешь

                          А в жовах с питонами и котлинами ты потом вынужден не забывать делать всё это клозабл и оборачивать спец хуйней

                          Вот такие рачки потом растут
                          https://github.com/JetBrains/intellij-community/blob/master/platform/util/src/com/intellij/openapi/Disposable.java
                          Ответить
                  • > это "raii" уровня джавы да питона.

                    RAII уровня крестов (пример с cplusplus.com)
                    std::mutex mtx;           // mutex for critical section
                    
                    void print_block (int n, char c) {
                      // critical section (exclusive access to std::cout signaled by locking mtx):
                      mtx.lock();
                      std::cout << 'kokoko';
                      mtx.unlock();
                    }
                    Почему не
                    LOCK(mtx){
                      std::cout << 'kokoko';
                    }
                    Ответить
                    • Х.з., потому что писатель мудак и не дочитал доку.
                      Ответить
                      • А как кошерно?
                        Ответить
                        • {
                              std::scoped_lock guard(mtx);
                              // kokoko
                          }


                          Ну или его старые братья.
                          Ответить
                          • since C++17

                            О, наконец сделали как положено. Отстал я от жизни.
                            Ответить
                            • Хелперы и в с++11 были, просто не такие няшные. Сразу несколько лочек не особо удобно было брать.
                              Ответить
                        • У него даже deadlock avoidance есть когда несколько лочек сразу берешь.
                          Ответить
                    • Не рекомендую документацию с cpluplus.com, там её питухи какие-то писали.
                      Ответить
                    • Можно использовать какие-нибудь скобочки из юникода

                      #define 【(mtx) mtx.lock()
                      #define 】(mtx) mtx.unlock()
                      Ответить
                      • Это не RAII, а решение типичного Сишника.

                        Я за \uD83D\uDD12

                        П.С Блядский utf8mb4

                        https://pastebin.com/E1Rqpmqx
                        error: macro names must be identifiers #define 【(mtx) mtx.lock()
                        Ответить
                    • #include <iostream>
                      #include <thread>
                      #include <mutex>
                      #include <cstdint>
                      
                      std::mutex mtx;
                      
                      #define LOCK(mtx) for( \
                        bool LOCK ## __LINE__ = ({mtx.lock(); true;}); \
                        LOCK ## __LINE__; \
                        LOCK ## __LINE__ = ({mtx.unlock(); false;}) \
                      )
                      
                      void print_block ()
                      {
                        for(size_t i = 0; i < 200; i++)
                        LOCK(mtx)
                        {
                          static char a[100] = {0};
                          for(size_t j = 0; j < 99; j++)
                          {
                            a[j] = 'A' + i % ('Z'-'A'+1);
                          }
                          std::cout << a << std::endl;
                        }
                      }
                       
                      int main() 
                      {
                        std::thread t1(print_block);
                        std::thread t2(print_block);
                        t1.join();
                        t2.join();
                      }
                      Ответить
                      • Тут это "## __LINE__" даже и не нужно т.к. за-shadow-ится
                        Ответить
                        • Правда это же кресты.

                          И на return/throw блокировка останется занятой.

                          https://ideone.com/CRz5nb
                          Time limit exceeded
                          Ответить
                          • // жаль что нельзя в макросе дефайн новый делать
                              #define return mtx.unlock(); return
                              LOCK(mtx)
                              {
                                static char a[100] = {0};
                                for(size_t j = 0; j < 99; j++)
                                {
                                  a[j] = 'A' + i % ('Z'-'A'+1);
                                }
                                std::cout << a << std::endl;
                                return;
                              }
                              #undef return
                            Ответить
                            • Там же целый паровоз операторов, которыми можно вылететь из скоупа.
                              goto, break, throw
                              Ответить
                              • #define LOCK(mtx) \
                                for( \
                                  struct \
                                    { \
                                      bool b; \
                                      struct S \
                                      { \
                                        S() { mtx.lock();} \
                                        ~S() { mtx.unlock(); } \
                                      } s;\
                                    } LOCK = {true,{}}; \
                                  LOCK.b; \
                                  LOCK.b = false \
                                )

                                Какое же дерьмо эти ваши кресты
                                Ответить
                                • А можно ли в крестах анонимной структуре (классу) прописать конструктор-деструктор? Ну чтоб без вложенной хуиты как тут
                                  Ответить
                      • Красота.

                        Тут сразу видно скоуп лочки.

                        И Гораздо эстетичнее крестопарашных
                        С++11
                        {
                          //код который здесь не блочится
                          std::lock_guard<std::mutex> guard(mtx);
                        }
                        С++17
                        {
                          //код который здесь не блочится
                            std::scoped_lock guard(mtx);
                        
                        }
                        Ответить
                    • В "D" можно еще сделать через "scope guards" такую хуйню
                      https://tour.dlang.org/tour/en/gems/scope-guards
                      import std.stdio : writefln, writeln;
                      
                      void main()
                      {
                          writeln("<html>");
                          scope(exit) writeln("</html>");
                      
                          {
                              writeln("\t<head>");
                              scope(exit) writeln("\t</head>");
                              "\t<title>%s</title>".writefln("Hello");
                          } // the scope(exit) on the previous line
                            // is executed here
                      
                          writeln("\t<body>");
                          scope(exit) writeln("\t</body>");
                      
                          writeln("\t\t<h1>Hello World!</h1>");
                      
                          // scope guards allow placing allocations
                          // and their clean up code next to each
                          // other
                          import core.stdc.stdlib : free, malloc;
                          int* p = cast(int*) malloc(int.sizeof);
                          scope(exit) free(p);
                      }


                      т.е. написать scope(exit) некаяхрень(); и она вызовется по выходу из скоупа
                      Ответить
                      • Який defer
                        Ответить
                      • Сильный инструмент. Им можно решить и проблему освобождения памяти, и проблему закрытия файлов, и проблему закрытия тегов разметки.

                        Получается стек для всего на свете, pop из которого завершению блока языка.
                        Ответить
                        • Не знаю. Мне не очень нравится.

                          А как этот стек выглядит в мышиных кодах? Нет ли перепитушни.

                          У меня давно витает завиральная мысль. Пора бы написать.

                          Почему ещё никто не догадался предложить разбиение функции на три необязательных секции.

                          1. intro
                          2. body
                          3. outro

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

                          body это сама функция.

                          А outro это что-то вроде деструктора функции. finally, которое выполняется всегда, после завершения body.

                          Только в отличие от finally, которое не видит скоуп try наш outro видит переменные верхнего уровня из intro и body.

                          Примерно так:
                          void example(){
                                  int* p = cast(int*) malloc(33);
                                  p[0] = 42;
                                  int x = send(&p); 
                                  if (!x) {
                                          return;
                                  }
                                  ....
                                  $Outro {
                                         if (p) free(p);
                                  }
                          }

                          По-моему это гораздо проще и решит 97% проблем освобождения ресурсов.
                          Ответить
                          • классическое же, еще со времен асембрела
                            void example(){
                                    int* p = cast(int*) malloc(33);
                                    p[0] = 42;
                                    int x = send(&p); 
                                    if (!x) {
                                            goto xyi;
                                    }
                                    ....
                                   xyi:
                                           if (p) free(p);
                            }
                            Ответить
                            • Мои знакомые процедуру GotoXY из модуля CRT называли «готохуй».
                              Ответить
                            • > классическое же, еще со времен асембрела

                              Это классическое говнище, которое сотни раз приводило к ошибкам.

                              Если бы люди постоянно не ошибались, никто бы не выдумывал RAII, умные указатели и сборщики говна.

                              Люди хотят писать return 42 и течь.
                              А не пердолиться с сохранением ответа во временную пельменную и goto в ебеня.

                              Соответственно в секции outer можно запретить return X, оставив её для cleanup.
                              Ответить
                              • Мне нравится, как сделали в Delphi и в FPC: присвоил значение псевдопеременной Result и выходи, когда хочешь, без потери результата.

                                Да и в классическом Паскале можно было присвоить и течь (в нём, правда, нельзя было читать это значение).
                                Ответить
                                • В «Бейсике» было похоже
                                  Function Foo (a as byte) 
                                       Foo = A + 1
                                  End Function

                                  Раньше мне этот подход совсем не нравился. Т.к. нужно было писать Exit Sub/Function. Но возможно в этом что-то есть.
                                  Ответить
                                  • В ассемблере никаких "функций" нет, именно поэтому я за ассемблер.
                                    Ответить
                                  • Это уже как минимум QB. Процедуры и функции слизали с Фортрана.
                                    Ответить
                                  • Этот подход либо хорошо забивается в голову, либо интуитивен. Студенты, которые только-только пришли после школы и изучают си, автоматически так пишут на си.

                                    Сразу понимают, какое си говно. Ни функцию посчитать, ни переменную назначить, ни степень посчитать язык не может.

                                    return pitux; // контринтуитивно
                                    
                                    not_nine = 3^2; // контринтуитивно
                                    
                                    x = 0;
                                    y = x*x;
                                    x = 2;
                                    not_four = y; // контринтуитивно
                                    Ответить
                                    • Я понял, про что последний пример.

                                      У математиков нет присвоения в том смысле, в котором оно есть в императивных ЯП. В императивные ЯП оно пришло из ассемблера, потому что там приходится переиспользовать регистры.

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

                                      Если нужно посчитать что-то новое, математик не переиспользует переменную, а объявляет новую.

                                      Правда, переиспользуемые переменные у математиков всё же есть: они используются под знаком суммы или произведения последовательности (ряда), интеграла, предела.
                                      Ответить
                                      • >> not_nine = 3^2; // контринтуитивно

                                        > У математиков нет присвоения в том смысле, в котором оно есть в императивных ЯП.

                                        Возможно вас заинтересует:
                                        https://govnokod.ru/27639
                                        Ответить
                                • В сишке же совместили сохранение возвращаемого значения и выход в едином операторе return, чем породили секту одновозвратников (иначе можно забыть вернуть значение).
                                  Ответить
                                  • В этом на самом деле есть смысл и удобство, пока не надо городить goto exit;

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

                                    Там есть довольно упоротая/оригинальная возможность разбивать процедуру на подпроцедуры (т.н. секции).

                                    А в хедере писать PERFORM и указывать порядок их выполнения, смешивая образы до полного безумия.

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

                                    Если выразить это в условном сишном синтаксисе выглядит примерно так
                                    void example()
                                        CO
                                        CO
                                        I
                                        CO to L
                                    {
                                       CO. puts("CO")
                                       BO. puts("BO")   
                                       L.  puts("L")   
                                       I.  puts("I ")
                                       
                                    }
                                    Output: 
                                    COCOI COBOL

                                    Ответить
                                    • Почти шитый код получается.
                                      Ответить
                                      • >Почти шитый код получается.
                                        Ага.

                                        Но я описал perform очень и очень упрощённо.

                                        Во-первых, вызовы секций могут быть описаны не только в хедере.
                                        И внутри секций можно писать вызовы других секций (рекурсивно с нахлёстом)

                                        Во-вторых PERFORM это аналог For, While, Repeat.. Until в одном флаконе, что кратно добавляет пиздеца.

                                        Последовательное исполнение за которое я написал это Basic PERFORM.
                                        Но там есть более интересные применения
                                        The PERFORM statement formats are:
                                            Basic PERFORM
                                            TIMES phrase PERFORM
                                            UNTIL phrase PERFORM
                                            VARYING phrase PERFORM


                                        Пример
                                        PERFORM PROCEDURE-NAME-1 THROUGH PROCEDURE-NAME-2
                                              VARYING IDENTIFIER-2 FROM IDENTIFIER-3
                                                    BY IDENTIFIER-4 UNTIL CONDITION-1
                                                 AFTER IDENTIFIER-5 FROM IDENTIFIER-6
                                                    BY IDENTIFIER-7 UNTIL CONDITION-2


                                        Описание у IBM с мозговзрывными блок-схемами
                                        https://www.ibm.com/docs/en/cobol-zos/4.2?topic=statements-perform-statement

                                        https://www.ibm.com/docs/en/cobol-zos/6.2?topic=statement-perform-varying-phrase


                                        По-моему один этот оператор настолько сложен, что сам по себе полностью Тьюринг полный.
                                        Ответить
                                        • Удобная фича. И код разделён на части, и эти части нигде не снаружи не светятся.

                                          Теперь понял, чего мне в языках программирования не хватало. Иногда шаг алгоритма хочется выделить, но он ещё не настолько самостоятелен, чтобы под него нужно было создавать функцию. Получается либо лапша на тысячи строк, либо куча функций, которые вызываются только в одном месте.
                                          Ответить
                                          • Гцц позволяет объявлять вложенные функции, захватывающие весь локальный контекст.
                                            Ответить
                                            • Да и в js можно сделать локальную функцию.

                                              Но это больше смахивает на замыкания.

                                              А в «Кобол» это логические блоки, скоупы. Больше похожие на метки.

                                              И эта фича довольно сильно меняет отношение к кодингу. Сразу чувствуется что у людей своя интерпрайзная атмосфера.

                                              Во-первых, код больше не уходит вбок на глубину (на экранах в 70х это было важно).
                                              Каждый скоуп просто выносится вниз. «Кобол» кстати ругали за то, что тело цикла может быть отделено от PERFORM.
                                              void ex(int toSearch){
                                              
                                              SEARCH.
                                                  for (int i=0;i<sizex;++i)
                                                      for (int j=0;j<sizey;++j)
                                                            LOOP
                                              
                                              
                                              LOOP.
                                              if (a){
                                                  if (toSearch == a[i][j]){ 
                                                     v =  i*sizey+j;
                                                     return;
                                                  }
                                              }
                                              }

                                              Во-вторых, бряк на метку и выход из двух сразу циклов перестаёт быть проблемой.
                                              Можно сделать выход из секции.
                                              Ответить
                                              • > бряк на метку и выход из двух сразу циклов перестаёт быть проблемой.
                                                Такой язык просрали. У меня из-за бряков не туда была куча ночей отладки. Гост с его проблемами от безобидного var нервно курит в сторонке.

                                                Появилось три опции вместо двух? Решил, что if недостаточно красив? Сосни, сучечка.

                                                while (pituz) {
                                                  if (syoma) {
                                                    c++;
                                                  } else {
                                                    break; // ok
                                                  }
                                                }
                                                
                                                while (pituz) {
                                                  switch (syoma) {
                                                    case 'perdoling': c++; break;
                                                    case 'svalka': fan = 1; break;
                                                    default: break; // fuuu blyad fuuu napiton
                                                  }
                                                }
                                                Ответить
                            • Уважаемые программисты, прекратите в качестве меток использовать слово "хуй".
                              Ответить
                          • > А как этот стек выглядит в мышиных кодах? Нет ли перепитушни.

                            Если там этот scope(exit) не завернут в какие-нибудь условия (т.е. этот вызов scope(exit) может быть, а может и не быть), никакого "стека" не требуется, т.к. это можно переписать как вызов этой питушни перед соответствующей "}"
                            Ответить
                            • Да и кстати, если заворачивать этот scope(exit) внутрь какого-нибудь условия, срабатывать он будет для скоупа в этом условии, так что никакой "стек" тут вообще не требуется
                              Ответить
                              • А ежели, положим, завернуть его не в исключение, а скажем, в армянский лаваш?
                                Ответить
                • З.Ы. Мне вот питонисты в своё время так и не рассказали, как идиоматично описать класс, которому надо джва открытых файла. Только пытались убедить, что это нинужно. Пришлось самой exit stack гуглить. Благо в питоне хоть он есть. У джавы с её скриптом и такого нет.
                  Ответить
                  • То ли дело ``Erlang'', где файл можно открывать либо по-княжески, когда спавнится процесс*, который следит за лайфтаймом процесса, создающего файл, и подчищающий его при кончине, либо по-царски, как в сишке.

                    * Он может вертеться на другом хосте, кстати. Network transparency, хо!
                    Ответить
                  • >олько пытались убедить, что это нинужно.

                    Всё не нужно, что сломалось
                    Всё не нужно, чего нет
                    Ответить
                • какие костыли ))

                  а напиши для трех ресурсов
                  Ответить
    • Ебать ты говнокодер. Въебал плюс за говно.
      Ответить
    • В «Cи» никаких «конструкторов» нету.
      struct Array
      {
          size_t size;
          int    *ptr;
      };
      Именно поэтому я за «Си».
      Ответить
      • Да один хер потом добавишь AllocArray да ResizeArray чтобы эти поля не заполнять...
        Ответить
      • В «Си» есть фабричный метод. Это даже хуже деструктора, потому что фабричный метод есть ещё и в JAWA...
        Ответить
      • .
        Ответить

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