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

    +1

    1. 1
    Поцаны, шестой уровень вложенности - это ок или говнокод?

    У вас обычно сколько?

    Запостил: subaru, 08 Ноября 2017

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

    • Я про отступы в коде.
      Ответить
      • Отступы не использую, для визуальной чистоты кода. Программист, неспособный разобраться в структуре чужого кода без отступов, - сущий даун.
        Ответить
        • а зачем разбираться в чужом коде?
          всегда проще свой написать
          Ответить
          • # свой написать

            Зачем свой писать? Достаточно нанять индуса и он всё сделает за тебя
            Ответить
            • индусу фиг объяснишь
              он по-русски не понимает
              Ответить
        • Значит это ты, падла, отступы не ставишь
          Ответить
        • > Отступы не использую
          Напитон!
          Ответить
    • extract method плачет
      или return с инвертнутым условием
      Ответить
    • namespace{
       class{
        method(){
          if(){} уже 4 получается
        }
       }
      }
      Ответить
      • А я обычно не добавляю отступ в неймспейсе. Это тупо.
        Ответить
        • А я не использую наймспейсы. Это тупо.
          Ответить
          • > Это тупо.
            согласен, не использовать неймспейсы -- тупо.
            Ответить
            • Сравнил неймспейсы и то, что можно использовать в их качестве в питоне - стало очень грустно, захотелось плакать.
              Ответить
          • И разные файлы тоже лучше не использовать. MyFile.cs и все
            Ответить
      • Открывающая скобочка на той же строке что и остальной код? В шарпике же на следующей принято вроде как?
        Ответить
        • да, именно.
          Her джавист вероятно
          Ответить
          • > namespace
            > шарпик
            > джава
            Ответить
            • ...и?

              Кстати, Namespaces плюс видимость на уровне модуля в тыщу раз пижже чем никому не нужные пакеты.
              Джава в очередной раз оказалась хуже шишарпа
              Ответить
              • Извените, не знал, что в сисярпе есть неймспейсы.
                Ответить
                • Извиняем: https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/namespace
                  На самом деле даже не в C# , а в .NET.

                  Полное имя класса, известное .NET, обычно звучит как System.Foo.Bar.Buz.
                  То, что C# позволяет сделать using и не писать полное имя это, по сути, сахар.

                  В общем всё как с пакетами в JVM, но в отличие от JVM они не влияют на доступ
                  Ответить
        • Должен заметить, что скобочка на той же строке пизже, чем на новой.
          Ответить
    • Смотря откуда начинать считать. Если начиная от тела функции то 3ий или 4ый еще ничего. Дальше уже начинает неслабо попахивать говнецом. Есть правда исключения, но они все равно тоже попахивают
      Ответить
    • Размер моей вложенности 21 см.
      Ответить
    • Нахуярил только что 9 уровень вложенности, потому что в goвне даже элемент в массиве так просто не найти, надо писать цикл.
      Ответить
      • package main
        
        import "fmt"
        
        func Find(n int, p func(int) bool) int {
        	for i := 0; i < n; i += 1 {
        		if p(i) {
        			return i
        		}
        	}
        	return -1
        }
        
        func main() {
        	a := []int{1, 2, 3, 4}
        	threeAt := Find(len(a), func(i int) bool { return a[i] == 3 })
        	fmt.Println("3 is at", threeAt)
        }
        Ответить
        • Умно. Спасибо за лайфхак. Держи плюсик в карму))
          Ответить
        • Но темплейтов нету и придётся для каждого типа такую функцию писать?
          Ответить
          • Про какую функцию речь? Find нужен только один на все типы слайсов, а вот лямбды на каждый чих писать замучаешься. Зато универсальненько:
            at := Find(len(xs), func(i int) bool { return xs[i].Name == "Vasya"; })
            Ответить
            • А, тьфу, Find вообще не обращается к коллекции.
              Ответить
            • В принципе, такой приём можно и в няшной поюзать, если включить гццизм про вложенные функции...
              Ответить
              • >>няшной
                >>вложенные функции.

                даже боюсь думать во что это разворачивается
                Ответить
                • > боюсь
                  И правильно делаешь... На х86 оно требует исполняемый стек, чтобы сгенерить на нём трамплин, который передаст адрес родительского фрейма в функцию.
                  Ответить
                  • Всмысли страничка со стеком должна быть executable?

                    То-есть они реально физически в стеке хранят код процедур вместе с параметрами?
                    Где-то между EBP и ESP (ну или просто где-то по ту стоону от EBP если fpo)
                    Ответить
                    • Да, страничка со стеком будет без NX (конпелятор попросит об этом в заголовке эльфа).

                      В момент взятия адреса локальной функции на стек помещается трамплин (что-то в духе mov ecx, ebp и jmp на настоящую реализацию). И адрес этого трамплина ты получаешь вместо адреса функции. Именно поэтому такое "замыкание" превращается в тыкву после выхода из родительской функции.

                      Костыль тот ещё...
                      Ответить
                    • Трамплин хранит не весь код процедуры, а только параметры, захватываемые замыканием (точнее, код копирования этих параметров) и джамп на код процедуры.
                      Ответить
                      • Напоминает Task Gateway из фичи "хардварное переключения контекстов", которой никто никогда не воспользовался
                        Ответить
                      • Да нету в трамплине знаний ни о захватываемых параметрах ни о коде процедуры. И копирования тоже нету. Тупо 2 асмовых инструкции - сунули указатель на родительский фрейм в регистр и джамп на вложенную функцию. По крайней мере на х86. А дальше вложенная функция сама разберётся - она и без трамплина знает лейаут родительского фрейма.
                        Ответить
                        • Спасибо за уточнение. Да, я наврал. Копирования нет, тупо указатель (фактически на родительский контекст). А относительные адреса параметров родительской функции и её локальных переменных заранее вычислит компилятор.
                          Ответить
              • не понял. зачем?

                просто числа вместо итераторов. что-то типа `std::find_if( 0, xs.size(), <predicate>)` должно работать.

                или я что-то в дискуссии не уловил?
                Ответить
                • >> в няшной поюзать
                  > <predicate>

                  Няшная == C (без плюсов)
                  Как ты предикат в сишечке напишешь, который в локальные переменные смотрит? Разве что хаки с void* context и кастами использовать.
                  Ответить
                  • в ц понятно сильно лучше чем вот это не сделаешь:
                    http://man7.org/linux/man-pages/man3/bsearch.3.html

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

                      Ну вот борманд и предлагает
                      https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
                      Ответить
                      • удивляет что до сих пор не в ц стандарте.

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

                        но так как в кресты это уже взяли - то не вижу смысла почему в ц аналога не включат.
                        Ответить
                        • > но так как в кресты это уже взяли

                          Удивляет, что шаблонов до сих пор нет в Ц стандарте. В кресты давно уже взяли, почему в Ц аналога до сих пор нет?
                          Ответить
                          • не знаю почему ты зеленишь, но шаблоны функций и структур - с к ним прицепленым нэйм манглингом - в ц очень бы и не помешали.
                            Ответить
                            • Для математических библиотек было бы полезно, чтобы по нескольку раз не писать одну функцию для float, double, long double.
                              Ответить
                              • > Для математических библиотек было бы полезно...
                                ... подумали сишкостандартизаторы и прикрутили очередной уродливый и бесполезный частный случай - tgmath.h
                                Ответить
                                • > Писать математику на няшной
                                  Лучше фортран, я совершенно серьёзно.
                                  Ответить
                                  • А не лучше математику писать на функциональных ЯПах?
                                    Ответить
                                    • > А не лучше математику писать на функциональных ЯПах?

                                      Если тебе не важен ПИРФОМАНС, то можно. На чём-то вроде хаски в теории можно что-то шустрое написать, но на практике сложно и муторно.

                                      Типично:
                                      https://izbicki.me/blog/fast-nearest-neighbor-queries-in-haskell.html
                                      https://habrahabr.ru/post/171425/
                                      Ответить
                          • Действительно, главное отличие C++ от Си — ООП. Но шаблоны не имеют никакого отношения к ООП (в ранних версиях C++ без шаблонов обходились).

                            Значит, по идее можно прикрутить шаблоны к Plain Си.
                            Ответить
                            • > Значит, по идее можно прикрутить шаблоны к Plain Си.

                              Я бы прикрутил уже только для того, чтобы посмотреть, как у @j123<цифры> пукан подгорит.
                              Ответить
                              • Ещё одна идея: прикрутить множества из SETL. К Паскалю множества прикрутили. Почему бы тогда не прикрутить их и к Си, ведь Си — такой же наследник Алгола, как Паскаль?
                                Ответить
                            • > шаблоны не имеют никакого отношения к ООП
                              А я думал, что шаблоны в крестах есть реализация параметрического полиморфизма.
                              Ответить
                              • OOP /= parametric polymorphism

                                OOP в стиле Java -- это subtyping (система типов, позволяющая неявно заменять значения определённого типа значениями его подтипов). Параметрический полиморфизм -- возможность определять термы с типом, зависящим от типов-переменных. Это ближе к Generic'ам
                                Ответить
                                • Мне кажется что всё это можно вообще без ООП.

                                  Вот такая функция параметрический полиморфизм или нет?
                                  Spam(name: T) -> List<T>
                                  Ответить
                                  • > Мне кажется что всё это можно вообще без ООП.

                                    СНауТ ровно это и сказал. Параметрический полиморфизм с выводом типов был уже в начале 70 реализован в ML, когда этих ваших «C#» и «Java» ещё и в проекте не было.
                                    Ответить
                                    • Ну, значит лет через 15-20 он станет мастхэв во всех мейнстримовых яызках.
                                      В джаве и генериков-то не было до пятой версии. Везде generic pointer был, всмысле Object.

                                      Почему люди, когда делали Java и C#, не осилили по началу даже вывод типов?
                                      Не умели? Жалели время на компиляцию?
                                      Почему императивные мейн-стрим языки отстают от ML на пол века?
                                      Ответить
                                      • Как только ты добавляешь OOP и subtyping к языку, систему вывода типов можно сразу выкидывать.

                                        Практически все современные гибридные языки не могут пользоваться Хиндли-Милнером. Для каждого придумывается наколеночная эвристика. То, что есть в C# и прочих Scala -- тухленькая имитация.

                                        > Почему императивные мейн-стрим языки отстают от ML на пол века?

                                        Я задаюсь тем же вопросом. Я слабо понимаю, куда всё движется по всем фронтам. JavaScript в браузере вместо Lisp-машин? Java и ООП вместо ML и модулей? Это прогресс? SRLY?
                                        Ответить
                                        • То-есть Хиндли-Милнер не работает для subtyping , и потому не пригоден для всех ЯПов где есть наследование? Надо бы в это погрузиться, возможно там кроется ответ на вопрос почему типизация в мейн-стриме такое говно.

                                          >> Я слабо понимаю, куда всё движется по всем фронтам
                                          Да, у меня тоже есть ощущение что всё в какой-то момент стало хуже.
                                          Возможно бум доткомов и популяризация веба привлекла массу php и javascript прогр людей, далеких от глубокого понимания, и они начали радостно изобретать инструменты, которые в других средах давно уже существуют.

                                          В самыхглавных мейнстримовых языках даже модульности нормальной нет.

                                          Вот это же какая-то битва с надувными мельницами в грязи:
                                          https://habrahabr.ru/post/312022/
                                          Ответить
                                          • > Вот это же какая-то битва с надувными мельницами в грязи:
                                            > https://habrahabr.ru/post/312022/
                                            выбрал инструмент под задачу
                                            @
                                            послал транспитухов, тайпитухов, питухJS, моду и 2016 напитон
                                            Давайте уже сделаем модным среди веб-модников выбирать инструмент под задачу. 2017 кончаются, а они пердолятся с инструментами и не пишут код.
                                            Ответить
                                        • > Как только ты добавляешь OOP и subtyping к языку, систему вывода типов можно сразу выкидывать.
                                          А можете простенько на качественном уровне пояснить, почему так получается?

                                          Нельзя ли в алгоритм вывода вставить куда-нибудь вместо "тип" - "самый старший предок типа", чтобы всё заработало? А, или тогда получится, что мы в некоторых случаях обрежем возможность использовать поля/методы потомков, если автоматом выберем родителя.
                                          Ответить
                                          • > "самый старший предок типа", чтобы всё заработало?

                                            Во-первых, не всегда понятно, о какой иерархии идёт речь.
                                            // псевдоэльфийский
                                            class A { def do : Unit → Unit }
                                            class B { def do : Unit → Unit }
                                            
                                            def f x = x.do ()
                                            Какой тип у f?

                                            Я не совсем понимаю, что значит "возвращать самого старшего предка". Наименее специфичный тип ты возвращать не захочешь, это будет какой-нибудь Object. Наиболее специфичный тоже возвращать не айс:
                                            static MyInterface compose(
                                                final MyInterface a,
                                                final MyInterface b) {
                                              return new Composition() { ... };
                                            }
                                            Вот тут мы намеренно хотим скрыть специфичный тип.

                                            В хиндли-милнере каждая функция имеет один наиболее общий тип; при добавлении сабтайпинга у каждой функций может быть множество типов, происходит комбинаторный взрыв вариантов. Т.е. в теории это может работать, на практике это медленно и сложно.
                                            https://stackoverflow.com/a/22533286/1683138
                                            Поэтому в OCaml такое "своеобразное" ООП (там подтип определяется не явным наследованием, а совместимостью интерфейса, по аналогии с модулями), а мейнстрим довольствуется локальными эвристиками.
                                            Ответить
                                            • > in a language without subtyping, the typing rules impose equality constraints on types. These are very nice to deal with during type checking, because they can usually be simplified immediately using unification on the types. With subtyping, however, these constraints are generalised to inequality constraints.

                                              Лол, я хотел что-то подобное написать, но решил, что понятие неравенства применительно к типам -- это слишком большие вореции.
                                              Ответить
                                    • > Параметрический полиморфизм с выводом типов был уже в начале 70 реализован в ML
                                      Вики говорит, что Simula появилась несколько раньше.
                                      Ответить
                                  • > Мне кажется что всё это можно вообще без ООП.
                                    Так ООП, он как скрипач -- не нужен.
                                    > Spam(name: T) -> List<T>
                                    Это эльфийский сигнатура функции или её тело?
                                    Ответить
                                    • Это эльфийский, ты прав.
                                      Ну пусть будет тело. А это важно?
                                      Ответить
                                      • Если List<T> -- это именно тип, а не конструктор пустого списка, то поздравляю, у тебя уже зависимые типы, потому что тип самой этой функции находится в другом универсуме, нежели T и List<T>. В привычном понимании параметрический полиморфизм более прозаичен,
                                        няпример:
                                        Spam(name: T) -> [] : List<T>

                                        (Проебать 1 аргумент типа T, и вернуть пустой список).
                                        Ответить
                        • В кресты это не взяли. В крестах намного более простая и безопасная вещь - контекст+функция. А это расширение пытается выдать каждой вложенной функции волшебный адрес, позвав который у тебя магически передастся и контекст... А всё это всего лишь чтобы поддержать унылые функции, которые дают передать только коллбек, но не контекст... И реализуется это дерьмо на всех популярных платформах через адские костыли (если вообще реализуется). Поэтому его никогда и не примут.

                          З.Ы. В паскале тоже была реализация вложенных функций (не полноценных замыканий, они тоже дохли на выходе из родительской). И там, емнип, нельзя было такую функцию куда-попало передать.
                          Ответить
                          • В Трубопаскале нельзя было брать адрес вложенных функций. Их можно было только вызывать из родительской функции. Поэтому о контексте и не парились.
                            Ответить
                            • > только вызывать
                              Ну если только вызывать - то и гцц трамплины не генерит. Но нахуй они тогда нужны? Просто чтобы поменьше переменных передавать? Как-то уныло.
                              Ответить
                              • Плюс ещё глобальный неймспейс не засоряется вспомогательными функциями, которые снаружи не очень нужны.
                                Ответить
                                • > глобальный неймспейс не засоряется
                                  Статики же... Если модуль на мегабайты не раздувать - никому они не помешают, имхо.
                                  Ответить
                                  • Ну тогда главная фишка в том, что «лишние» параметры не передаются, а тупо захватываются из родительского контекста против нашей воли, даже когда это не очень нужно.

                                    У ООП аналогичная фишка: экономия аж на целом одном аргументе функций (во все методы неявно передаётся self).
                                    Ответить
                                    • > неявно передаётся self
                                      Скажи это петону.
                                      Ответить
                                      • Тогда в Питоне ООП вообще не нужно?
                                        Ответить
                                        • Не понял. Какая связь с явным получением self и ооп?
                                          Или главный смысл ООП в неявной передаче указателя на объект?
                                          Ответить
                                          • Ну вообще-то смысл ООП ещё и в наследовании, но на Говнокоде говорят, что наследование не нужно.
                                            Ответить
                                      • > Скажи это петону.
                                        В петоне передаётся неявно. Явно только принимается.
                                        Ответить
                                  • vanished
                                    Ответить
                            • >>Трубопаскале
                              >>вложенных
                              орлы?
                              Ответить
                              • function halfsum(x, y: Real): Real;
                                    function Half(z: Real): Real;
                                        begin
                                            Half := z / 2
                                        end;
                                    begin
                                        halfsum := Half(x) + Half(y)
                                    end;


                                Что не так?
                                Ответить
                                • Я последний раз писал на TurboPascal в 1999 г, и таких штук там не помню.
                                  Но просто мелкий был. Надо скачать паскаль и проверить, может быть
                                  Ответить
                                • Вы все врете
                                  https://s18.postimg.org/6m2pl15x5/fail.png

                                  Небось в дельфями попутали?

                                  PS: там возврат выше конечно, но если его убрать все равно не работает
                                  Ответить
                                • Более аутентично
                                  https://ibb.co/dsBxYG
                                  Ответить
                                  • Оба раза ошибка. Вложенную функцию нужно писать ПЕРЕД блоком begin...end.

                                    Мой код скопировать слабо́?

                                    Что-нибудь объявлять ПОСЛЕ слова begin можно было только в Алголе. Ну ещё в няшной можно объявлять переменные после фигурной скобки.

                                    P.S. Ещё в качестве подсказки: локальные переменные в Паскале объявляются между заголовком функции и словом begin. Там же объявляются и вложенные функции.
                                    Ответить
                                    • да, так работает.

                                      Там перед begin же блок с переменными, видимо то что будет сразу класться на стек, наверное потому там и функция
                                      Ответить
                                      • А указатель, если я не ошибаюсь, на вложенную не берётся, даже если объявить её с директивой ;far; или после {$F+}.
                                        Ответить
                                        • А почему, кстати?

                                          Где-то же она живет, значит можно всегда найти offset ее относительно близжайшего адреса, способного стать началом сегмента (кратный 10h наверное) и ввернуть far адрес.

                                          и jmp туда сделать
                                          Ответить
                                          • Распаковал TP, проверил. Указатель на вложенную функцию брать можно, но только безликого типа pointer (аналог сишного void *). Указатель процедурного типа не берётся (видимо, для того, чтобы не пытались вызывать вложенную функцию снаружи).
                                            Ответить
                                            • Но можно обмануть TP: сначала положить указатель в переменную типа pointer, а потом использовать приведение типа. Вызывать функцию по такому указателю я не пробовал.
                                              Ответить
                          • https://s18.postimg.org/6m2pl15x5/fail.png
                            Ответить
                            • Икарус уже объяснил что надо было перед begin писать
                              Ответить
                        • > если нужна функция - то запихни ее куда официально, что бы и другие могли пользоватся
                          Тогда и статики стоило запретить, они ж нереюзабельны.
                          Ответить
                          • И локальные переменные, хули.
                            Ответить
                            • И сделать всё иммутабельным!
                              Ответить
                              • как в свифте или котлине

                                Вообще говоря иммутабельность лучше мутабельности почти всегда (кроме руби, где мутабельны даже строки)
                                Ответить
                          • # статики стоило запретить, они ж нереюзабельны

                            Но чем же это?
                            Ответить
                            • И правда. Просто пишешь всю программу в один файл и все реюзабельно.
                              Ответить
                              • Ну зачем в один? Можно использовать #include.
                                Ответить
                                • мысль инклюдить сишные файлы (с реализацией) мне нравится.
                                  Врата в ад откроются сразу же
                                  Ответить
                                  • Инклюдники с реализацией уже широко используются: с инлайн-функциями или с крестошаблонами.
                                    Ответить
                                  • Видел код, где в фортрановских файлах сишным препроцессором инклюдили внешний файл с объявлением локальных переменных.

                                    В каждой функции по инклюду.
                                    Ответить

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