ЙажаСценарий / Говнокод #27991 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
function fib<T>(n: T) {
    return n <= 2 ? n : fib(n - 1) + fib(n - 2);
}

function main()
{
  print (fib(5));
  print (fib(6.0));
}

я вам принес "рекурсивные генерики"..... внимание вопрос... а каким таким хером получилось вычеслить тут возвращаемый тип, а ?

Запостил: ASD_77 ASD_77, (Updated )

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

  • если бы вы знали какое это гов-но рекурсивные темплейты... просто ад
    Ответить
      • > типы рекурсивные

        Возможно вы имели в виду индуктивные?
        Ответить
      • ты все проспал... рекурсивные типы уже были:
        type BadFlatArray<Arr, Depth extends number> = {
            obj: {
                "done": Arr,
                "recur": Arr extends ReadonlyArray<infer InnerArr>
                ? BadFlatArray<InnerArr, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth]>
                : Arr
            }[Depth extends -1 ? "done" : "recur"]
        }["obj"];
        
        declare function flat<A, D extends number = 1>(
            arr: A,
            depth?: D
        ): BadFlatArray<A, D>[]
        
        function foo<T>(arr: T[], depth: number) {
            return flat(arr, depth);
        }
        
        function main() {
            foo<number>([1.0, 2.0], 2);
        }
        Ответить
  • > внимание вопрос... а каким таким хером получилось вычеслить тут возвращаемый тип, а ?

    В яжасцрипт только один численный тип, float64?
    Ответить
  • > а каким таким хером получилось вычеслить тут возвращаемый тип

    В момент инстанциации?
    Ответить
      • Ну вот когда инстанциируется в fib(5), тогда и определится... В общем-то в крестах оно тоже прекрасно работает.
        Ответить
        • А как работает вот такой код?

          proc fib[T](n: T): T =
            return if n > 2: fib(n - 1) + fib(n - 2) else: n
          
          echo $fib[float](6.0)
          echo $fib[int](5)
          Ответить
          • Я не знаю как у ОПа реализовано, но скорее всего он инстанциирует на каждый простой тип.
            Ответить
            • То есть, если туда передать каку-нибудь обёртку IntegerJsonSerialisable, то всё попячится?
              Ответить
              • Ну там скорее всего будет один инстанс под Object или даже полный юнион со всей хуйнёй.
                Ответить
                • ответ.... у любой рекурсивной функции всегда есть конец.. как не крути. вот это конец всегда говорит какой тип возврата
                  Ответить
                    • Ну или как-то так
                      template <typename T>
                      auto shit(T a)
                      {
                        return shit(a);
                      }


                      Рекурсивная функция вполне может "зациклиться".
                      То, что рекурсивная функция не зареркурсируется до бесконечности, еще надо доказать
                      Ответить
                        • Её не обязательно запускать, например пишешь:
                          auto f = shit<int>;
                          И получишь ошибку конпеляции
                          Ответить
                          • > ошибку конпеляции

                            Конпелятор подумает -- "бесконечная функция без побочек -- это UB, значит она не будет вызвана, значит можно выбрать любой тип, пусть будет void".
                            Ответить
                          • Кстати, вот тут
                            template <typename T1, typename T2>
                            T1 shit(T2 a)
                            {
                              return shit(a);
                            }
                            
                            auto f = shit<int, int>;
                            какая-то странная ошибка
                            error: no matching function for call to ‘shit(int&)’
                            Ответить
                            • > странная ошибка

                              Ниже конпелятор тебе поясняет эту ошибку: template argument deduction/substitution failed, couldn't deduce template parameter `T1'.

                              Т.е. он в момент конпеляции четвертой строчки искал какой-нибудь подходящий shit, но вариант с шаблоном не подошёл т.к. невозможно определить T1, а других вариантов и нету.
                              Ответить
                              • А, он пытался выяснить тип возвращаемого значения и просто перебирал возможные?
                                Ответить
                                  • Он подбирал какую из реализаций shit позвать.

                                    Но ты не указал T1 в строке 4 явно, а вывести его (по правилам крестов, когда вывод от аргументов к результатам) нельзя. Поэтому данный шаблон не подошёл. А других вариантов не нашлось.
                                    Ответить
                      • у этой функции хоть она и бесконечная всегда есть тип возврата т.е. 0 (int32)
                        template <typename T>
                        auto shit(T a)
                        {
                          if (a == 0) return 0;
                          return shit(a);
                        }
                        Ответить
                        • С тем же успехом она имеет тип int32 | "что угодно". Можно проверить: в первой строчке мы возвращаем 0, что соответствует. Во второй строчке она возвращает int32 | "что угодно", что тоже норм.

                          Да, это какой-то тип содержащий ноль, но почему int32? В принципе, подходит любой другой тип с нулём. И функция может вернуть что угодно при a != 0.
                          Ответить
                          • вернуть она не может что угодно ... есть только одно решение только при одном значении ... это если а = 0 то и результат = 0. если а != 0 т.е. значение неопределенно... (неопределенно - это не значит что угодно .. это значит мы не может определить т.к. процедура определения не имеет конца.
                            Ответить
                            • поэтому ответ всегда будет тип "int32". может ли когда либо shift изменить тип возвращаемого значения? нет не может. значит первый тип, который мы можем определить и есть тип возврата функции.
                              Ответить
                            • Ты уже второй раз за тред решаешь проблему останова. Астанавись!
                              Ответить
                              • Он ее решит, и получит нобелевскую премию, а вы будете посрамлены.

                                Он и про P=NP докажет
                                Ответить
                          • в коде возвращаемы тип всегда union { int32 v1, float v2 }; т.к. тип shit это всегда тип первого вернутого результата и тип shit ни при каких условиях не меняется

                            template <typename T>
                            auto shit(T a)
                            {
                              if (a == 0) return 0;
                              if (a == 1) return 1.0;
                              return shit(a);
                            }
                            Ответить
                            • > тип shit ни при каких условиях не меняется
                              В данном случае, возможно.

                              Но перепиши код как
                              template <typename T>
                              auto shit(T a)
                              {
                                if (a == 0) return 0;
                                if (a == 1) return 1.0;
                                return shit(a - 1);
                              }

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

                                Тайпскрипт -- это не система доказательства теорем, сойдёт и более консервативный тип в духе int | float или даже any...
                                Ответить
                                • > сойдёт и более консервативный тип в духе int | float или даже any...

                                  ... и возвращаемое значение функции было разработано настолько, что туда помещался любой объект.

                                  Вообще в тайпскрипте скучно. Не то, что в крестах — перегрузка операторов, (частичная) специализация, ADL... Вопрос, что вызовется, может стать увлекательной головоломкой.
                                  Ответить
                                  • > что туда помещался любой объект

                                    Но с ним ничего нельзя было сделать, не вытащив обратно с помощью каста.
                                    Ответить
                              • не верно... аргумент "a - 1" не меняет ни тип результата "return 0", ни "return 1.0".. это значит что и при a и при (a-1) возвращаемый тип всегда один. это "(int | float)"
                                Ответить
                                • >аргумент "a - 1" не меняет ни тип результата
                                  В С++ есть перезгрузка операторов

                                  Яблоко минус int может быть груша
                                  Ответить
                                  • ну и что ... еще раз...поймите что код в функции shit который возвращает результат. это return и в независимости от кода в теле... типы возвращаемых данных не меняет
                                    Ответить
                                    • #include <iostream>
                                      
                                      template <typename T>
                                      auto shit(T a)
                                      {
                                        if (a == 0) return 0;
                                        if (a == 1) return 1.0;
                                        return shit(a - 1);
                                      }
                                      
                                      struct foo
                                      {};
                                      
                                      
                                      struct bar
                                      {
                                      //...
                                      //...
                                      
                                      int main()
                                      {
                                          std::cout << shit(bar{});
                                      }
                                      
                                      > Hi

                                      Предлагаю поработать нейронкой и дописать код, чтобы работало поведение.
                                      Ответить
                                    • А можно переписать эту фразу согласовав слова по правилам русского языка?
                                      Ответить
                                      • там все просто.
                                        1) return shit(a - 1) какой имеет возвращаемый тип? случайный? - нет. он всегда предопределён. а что определяет возвращаемый тип функции shit? это строка "return 0" и строка "return 1.0". больше return в коде нет. значит список типов возвращаемых в shit - всегда предопределен и он конечен.
                                        Ответить
                                        • >- нет. он всегда предопределён
                                          к сожалению, нет. Он зависит от того, какого типа выражение "a - 1".

                                          Допустим, оно типа "яблоки".

                                          Но какого типа выражение "яблоки минус 1"?

                                          Допустим, оно типа "апельсины".

                                          Но какого типа выражение "апельсины минус один"?

                                          И так до бесконечности.

                                          Когда Алан Тюринг это понял, он обмокнул ножик в яде, разрезал яблоко, и съел половинку... и погиб:((((
                                          Ответить
                                          • Добавь к этому, что где-то ещё может быть
                                            template <>
                                            auto shit<апельсин>(апельсин a)
                                            {
                                                return shit(a * a) + shit(a.съесть());
                                            }

                                            И всё становится просто прекрасно и легко вычисляемо.
                                            Ответить
                                            • Это явное инстанциирование шаблона для кейса "апельсин"?

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

                                              Кресты такие кресты
                                              Ответить
                                            • мы уже определили что данный код не компилируется.
                                              Ответить
                                          • я не вижу как а-1 делает возвращаемый тип "строка" или "гвоздь" у функции shit ... покажите мне в какой строке это происходит
                                            Ответить
                                            • Держи. Вызывается оригинальный shit и каким-то сраным образом возвращает строку. Удивительное рядом.
                                              #include <iostream>
                                              #include <typeinfo>
                                              
                                              template <typename T>
                                              auto shit(T a)
                                              {
                                                std::cout << "Called shit with " << typeid(T).name() << '\n';
                                                if constexpr (a == 0) return 0;
                                                if constexpr (a == 1) return 1.0;
                                                return shit(a - 1);
                                              }
                                              
                                              struct foo
                                              {};
                                              
                                              
                                              struct bar
                                              {
                                                  foo operator-(int)
                                                  {return foo{}; }
                                                  
                                                  bool constexpr operator==(int)
                                                  {return false;}
                                              
                                              };
                                              
                                              template<>
                                              auto shit<foo>(foo)
                                              { return "Hi"; }
                                              
                                              
                                              
                                              int main()
                                              {
                                                  std::cout << shit(bar{});
                                              }


                                              http://coliru.stacked-crooked.com/a/6f521a764aef91f5
                                              Ответить
                                              • ты тут изменил функцию shit при специализации ... и это уже не рекурсивный вызов. это вызов совсем другой функции
                                                Ответить
                                                  • а мой компилятор не позволяет говнять код... поэтому и результат прогнозируемый
                                                    Ответить
                                                  • я только сейчас понял какое - это гав-но ваш С++. это получается что любой левый может врубить свою специализацию на уровне сборки т.к. кто первый присоединился тот и герой и весь код пойдет по "пиз.де"
                                                    Ответить
                                                    • Ну поэтому не надо перегибать палку со специализациями...

                                                      Так то да, бывают забавные эффекты, когда один цпп файл видит хедер со специализацией, а во второй его подключить забыли и там работает общий случай. Но это в общем-то даже не UB, просто неприятные различия в поведении.

                                                      > кто первый

                                                      Не, там всё сложнее. В каждой точке, где ты вызываешь функцию, составляется список вариантов, фильтруется, сортируется и выбирается "самый подходящий". Если выживет несколько кандидатов -- будет ошибка, а не первый.
                                                      Ответить
                                                      • на уровне линкера идет правило.. если я вижу func$xxx$1 (которые темплейт) из obj1 и точно такой же из obj2 то линькер возьмет первый и проигнорирует второй...
                                                        Ответить
                                                        • > на уровне линкера

                                                          Это другое, это нарушение ODR когда одноимённая функция в разных юнитах трансляции как-то получилась с разным телом.

                                                          А у разных специализаций имена разные, линкер их не мержит между собой.

                                                          З.Ы. Но если ты напишешь в джвух файлах разные специализации для одного типа -- вот там да, имена совпали, нарушение ODR, UB, кишки, распидорасило.
                                                          Ответить
                                                      • >просто неприятные различия в поведении.

                                                        Q: Почему одна и та же функция у меня в одном месте тормозит, а в другом летает?
                                                        A: Потому что нужно подключить petuh.hpp.

                                                        Реально ведь магия уровня Ruby: подключаешь файл, и всё начинает работать иначе
                                                        Ответить
                                          • еще раз... то что я съел не то же самое что я выкакал.. я всегда какаю говном .. без разницы что я съел
                                            Ответить
                    • C:\temp\MLIR_to_exe>clang++ -emit-llvm -O0 -c -S 1.cpp 1.cpp:7:10: error: function 'shit<int>' with deduced return type cannot be used before it is defined return shit(a); ^ 1.cpp:12:11: note: in instantiation of function template specialization 'shit<int>' requested here
                      Ответить
                      • Вообще, эта конструкция ужасна тем, что она может вернуть любой тип. Включая тот, у которого нет конструкторов. Именно поэтому в Coq её запретили.
                        Ответить
                  • > у любой рекурсивной функции всегда есть конец..

                    Наконец-то кто-то решил проблему остановки.
                    Ответить
        • А такой?
          from typing import TypeVar
          
          T = TypeVar('T') 
          
          def fib(n: T) -> T:
              return fib(n - 1) + fib(n - 2) if (n > 2) else n
          Ответить

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

Семь раз отмерь — один отрежь, guest!

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


    8