Вступление: Программирование умерло. Да здравствуют правила!

Помните времена, когда код писали люди, а не роботы? Когда творчество ценилось выше слепого следования стандартам? Современные языки — это не эволюция, а индульгенция для лентяев, которые боятся мыслить. Rust, Go, TypeScript — фабрики по производству посредственности, где каждый ваш шаг контролирует «всезнающий» компилятор. Пора назвать вещи своими именами: мы променяли гениальность на мнимую безопасность, а свободу — на кандалы статических проверок. Это катастрофа. Увы, не все это понимают.

Хотите узнать, почему? Читайте дальше!

1. Документация: От шедевров к инструкциям от IKEA

Помните Perl? Помните секцию SYNOPSIS в начале каждого документа? Чаще всего кроме этого раздела читать особо ничего и не требовалось. Мало того, можно было сформулировать правило: если интерфейс Вашей библиотеки не показывает лаконичного синопсиса, то скорее всего Вы сделали плохую библиотеку!

Perl с его POD — это «Война и мир» документации. Каждый модуль на CPAN начинался лаконичным примером, который в две строки объяснял, как творить магию. Не нужно было рыться в типах или трейтах: открыл доку — и сразу видишь живой код, а не бюрократическую отписку.

Современные языки? Добро пожаловать в ад автосгенерированной документации! Rust-крейты похожи на налоговые кодексы:

/// Конвертирует строку в число (написано роботом для роботов).  
/// # Параметры  
/// - `s`: &str (потому что String — это слишком человечно)  
/// # Возвращает  
/// - Result<i32, ParseError> (ведь вы обязаны обработать даже апокалипсис)  
pub fn parse(s: &str) -> Result<i32, ParseError> { ... }  

Где примеры? Зарыты где-то между #[derive(Debug)] и impl FromStr. Чтобы понять, как использовать функцию, вам понадобится докторская степень по расшифровке типов. Perl-сообщество уважало разработчика, современное — презирает, подсовывая вместо примеров стену текста.

Вывод: Документация умерла. Её место заняли автогенерированные мануалы для мазохистов.

2. Статическая типизация: Религия для параноиков

«А что, если передашь строку вместо числа?» — пугают адепты статики. Давайте посмотрим правде в глаза:

  • Львиная доля багов — логические. Ваш код может идеально пройти проверку типов — и всё равно уронить спутник на Марс, потому что вы перепутали > и >=.

  • Динамические языки — это свобода. В Perl "25" + 10 даст 35, а не ошибку — потому что язык создан для решения задач, а не для удовлетворения паранойи компилятора.

  • Статика — это бюрократия. Посмотрите на этот «идеальный» код на Rust:

    let total: f64 = price.parse::<f64>().unwrap() * quantity.parse::<f64>().unwrap();  

    Теперь сравните с Perl:

    my $total = $price * $quantity;  

    Perl понял, что вы имели в виду, а Rust требует клятву верности типам — даже если вы умнее компилятора.

Ирония: Статическая типизация не спасает от дурака. Она спасает дурака от необходимости думать.

3. Алгебраические типы: Величайший обман XXI века

АТД преподносят как прорыв. На деле — это костыль для статиков, которые боятся признать: динамическая типизация была права.

Пример: Парсинг YAML в Rust требует enum’а на 15 вариантов. Каждый match превращается в ад ветвлений:

match yaml {
   Yaml::Real(_) => { /* ... */ },
   Yaml::Integer(_) => { /* ... */ },
   Yaml::String(_) => { /* ... */ },
   // ... ещё 12 вариантов
   _ => panic!("Вы не обработали этот случай, потому что Rust вас ненавидит"),
}

Perl-подход:

my $value = parse_yaml($input);
# Обрабатываю то, что нужно. Остальное? Не моя проблема.

Итог: АТД — это статики пытаются имитировать свободу динамических языков. Получается как всегда: сложно, многословно, и всё равно небезопасно.

4. Иммутабельность: Бунт против законов физики

Второй закон термодинамики гласит: энтропия растёт. Это следствие (или доказательство) того, что мир мутабелен. Но функциональщики решили, что они умнее Вселенной!

Последствия:

  • Иммутабельные структуры — это обман. Даже Haskell, истошно кричащий о чистоте, прячет мутации в IO-монадах.

  • Гонки данных? Не смешите мои тапочки! Проблемы с гонкой решаются архитектурой, а не фанатизмом. Go с его горутинами и каналами — живое доказательство.

  • Перформанс? Правильные пацаны используют мутабельность, а не рекурсию! Попробуйте обновить 1 млн объектов в «иммутабельном» цикле — и ваше приложение будет удалено значительно раньше, чем успеет доработать!

Сарказм: Если вам так нравится иммутабельность — отключите клавиатуру и пишите код на камне. Это на 100% иммутабельно!

5. Философия: Как убить креативность за 10 лет

Perl дарил свободу:

  • TMTOWTDI — «Есть больше одного способа сделать это».

  • KISS — «Не усложняй».

Современные языки заменили это на:

  • TIOOWTDI (There Is Only One Way To Do It) — как в Go, где даже циклы только for.

  • KICC (Keep It Complicated, Comrade) — как в Rust, где простой скрипт требует 100 строк из-за проверок типов.

Итог: Современные языки — это школы для послушных детей. Хотите творить? Вас накажут компилятором.

Самое время вернуться к истокам!

Пока статики спорят о null-safety, а функциональщики фапают на монады, неиспорченные программисты делают работу. Они не боятся мутабельности, не тратят часы на аннотации типов и вместо многострочных эссе в документации пишут короткие текстовые примеры с подкраской синтаксиса.

Они пишут код, который работает — и работает хорошо!

Манифест (Призыв к бунту)

  1. Долой тиранию типов! Используйте Python, Perl, Raku — всё, что не душит вашу креативность.

  2. Документируйте как художники. Пусть примеры будут яркими, а не спрятаны в автосгенерированном шуме.

  3. Мутировать — это естественно. Перестаньте бояться изменений — и ваш код оживёт.

Программирование — это искусство. А искусство не терпит правил. Верните себе право творить — или смиритесь с участью винтика в фабрике кода.

Примечание

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

А в конце дискуссии можно попросить его обобщить суть до статьи.

Прошу прощения, но эта статья автосгенерирована ИИ, я лишь поправил некоторые особенно резкие выражения.

Комментарии (290)


  1. SevAnt
    31.01.2025 09:00

    1. Мутировать — это естественно. Перестаньте бояться изменений — и ваш код оживёт.

    Ага будет жить своей жизнью )))


    1. ednersky Автор
      31.01.2025 09:00

      программы, могущие писать другие программы — самые счастливые программы на свете

      из книги Хювенена, Сапеняна

      «Мир Лиспа», 1985


      1. SevAnt
        31.01.2025 09:00

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


        1. ednersky Автор
          31.01.2025 09:00

          осталось понять: кто же населяет мир без шуток и юмора.


        1. Inoi-zxz
          31.01.2025 09:00

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


    1. pda0
      31.01.2025 09:00

      Типа, ловите хаосита. :)


  1. miksoft
    31.01.2025 09:00

    В Perl "25" + 10 даст 35

    А почему не "2510" ?

    Я как-то больше привык, что первый операнд задаёт тип.


    1. vadimr
      31.01.2025 09:00

      Конкатенацию нет смысла обозначать плюсом.

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


      1. miksoft
        31.01.2025 09:00

        Дело не в конкретном кейсе. Дело в том, что в разных языках неявные вещи трактуются по-разному. И без опыта работы с конкретным кейсом в конкретном языке или без прочтения документации может быть разное понимание кода разными людьми.


        1. vadimr
          31.01.2025 09:00

          В буквальном смысле с вашим утверждением сложно поспорить. Но, тем не менее, существует определённая массовая культура программирования, благодаря которой после изучения нескольких языков – следующий, если он не слишком экзотический, уже можно в основном понять и не читая инструкцию. И в этом отношении плохо придумывать новые несообразности на ровном месте, если новые конструкции не имеют какого-то глубокого смысла. Ту же самую конкатенацию зачем обозначать плюсом? Чисто поржать?


      1. IUIUIUIUIUIUIUI
        31.01.2025 09:00

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

        Не понял. Из коммутативности плюса следует, что оба операнда абсолютно равноправны с точки зрения определения типов. Если вы запретили использовать первый, то и второй нелзья (потому что a + b = b + a, и, следовательно, ∀P. P(a + b) ⇒ P(b + a)).


        1. vadimr
          31.01.2025 09:00

          Имелось в виду, что типы операндов должны входить в результат на одинаковых основаниях, а не только первый или только второй. Как в действительности обычно и происходит.


    1. ednersky Автор
      31.01.2025 09:00

      на эту тему есть исследование Ларри Уолла

      вкратце, в Perl оператор плюс ТОЛЬКО математический

      а во многих языках есть двусмысленность между математическим плюсом и строковой конкатенацией


      1. eeemp
        31.01.2025 09:00

        А как же творчество и свобода? Что это за оператор плюса который только математический? Долой эту тиранию!


        1. ednersky Автор
          31.01.2025 09:00

          Вот! Вы начинаете проникаться!


        1. a1111exe
          31.01.2025 09:00

          А как же творчество и свобода? Что это за оператор плюса который только математический? Долой эту тиранию!

          Perl строг, там такого нельзя!

          Псст... Только тише, шёпотом - если очень хочется, то можно:

          $ perl -E '
          package String;
          
          use overload 
            q(+)  => \&concatenate,
            q("") => sub { $_[0]->{v} };
          
          sub new {
            my ($class, $v) = @_;
          
            return bless { v => $v }, $class;
          }
          
          sub concatenate {
            my ($self, $str, $swapped) = @_;
          
            return String->new($str . $self->{v})
                  if $swapped;
            return String->new($self->{v} . $str);
          }
          
          1;
          
          my $str = String->new("Hello");
          
          say $str + " World";
          say "World " + $str;
          say $str + " Goodbye " + 100 + " gramm nalivai";
          say 2 + 3;
          '
          Hello World
          World Hello
          Hello Goodbye 100 gramm nalivai
          5

          Ничего не показывал, ничего не рекомендовал, просто мимо проходил. Перегрузка операторов зло. Алкоголь зло. Люди зло.

          /s


    1. JBFW
      31.01.2025 09:00

      как уже ответили - "+" это сумма, "." - это конкатенация строк.
      на уровне синтаксиса языка решена проблема неоднозначности, и такого как в js здесь нет.


    1. Wesha
      31.01.2025 09:00

      А почему не "2510" ?

      Мюллер, опять вы за своё!..


    1. miksoft
      31.01.2025 09:00

      Кстати, так и не смог вспомнить откуда у меня в голове про первый операнд.
      Из того, что смог вспомнить - не арифметическое сложение, а UNION [ALL] из SQL - там типы данных всех входящих наборов данных приводятся к типам первого из них.


  1. rukhi7
    31.01.2025 09:00

    Программирование — это искусство. А искусство не терпит правил. Верните себе право творить — или смиритесь с участью винтика в фабрике кода.

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

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

    Правила важны, только не надо их придумывать самому, не надо терять связь с реальностью.


    1. flancer
      31.01.2025 09:00

      Интересно, художники, которые получили признание после смерти, делали добротный продукт при жизни. Но почему-то признание при жизни не получили.

      И второй момент, мастера, которые очень хорошо освоили техническую часть предметной области, зачастую так и остаются мастерами, которые очень хорошо освоили техническую часть предметной области. Есть масса таких мастеров, которые не получили признание ни при жизни, ни после смерти.

      Всё-таки получается, что помимо технической части предметной области, есть ещё что-то, что является искусством. А вот этому, я полагаю, научить нельзя, а разучить - можно. Искусство, это то, что устанавливает новые связи с реальностью. Связи, которых не было до, которые не прописаны в существующих правилах.


      1. rukhi7
        31.01.2025 09:00

        А вот этому, я полагаю, научить нельзя, а разучить - можно.

        Если научить нельзя- это значит это врожденная способность, и значит вы считаете что есть особенные люди, которые способны к исскусству от рождения, такие сверх человеки? О чем вы?

        Имели ввиду что научить нельзя, можно только самому научиться на собственном опыте?


        1. frt-ok-g
          31.01.2025 09:00

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


        1. flancer
          31.01.2025 09:00

          О том, что все люди разные. Некоторые с лёгкостью делают то, чему другие так и не смогут научиться за всю жизнь.


        1. Inoi-zxz
          31.01.2025 09:00

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


      1. rukhi7
        31.01.2025 09:00

        Искусство, это то, что устанавливает новые связи с реальностью.

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

        Энштейна действительно никто не мог научить теории относительности. Это факт.


      1. aamonster
        31.01.2025 09:00

        А вот этому, я полагаю, научить нельзя, а разучить - можно.

        То, что чему-то не научились учить – не значит, что это невозможно. Может, не каждого, но количество творцов запросто может стать куда больше, чем сейчас.


        1. flancer
          31.01.2025 09:00

          Да, может. Да, не невозможно. Можно научить безрукого плавать. И безногого тоже можно. И количество пловцов запросто может стать куда больше, чем сейчас. Но плавать они будут куда куже, чем Майкл Фелпс в отрочестве. Любой из них. Каждый.


          1. aamonster
            31.01.2025 09:00

            Возможно, если реально проверить население на способности к плаванию – окажется, что есть куча чуваков потенциально круче Фелпса :-)


            1. flancer
              31.01.2025 09:00

              Уверен, что так и будет. Но стоимость этой акции не окупится тем знанием, что именно вот эти чуваки куда круче, чем чувак Фелпс :)


    1. Inoi-zxz
      31.01.2025 09:00

      Представляете ли вы сколько гениальных программистов потеряно в России лет 30-20 назад только по тому - что не было приличного рускоязычного языка программирования! Не знаю появился ли он сейчас, но когда ты не понимаешь смысл команд которыми оперируешь - далеко не уедешь, особенно когда небыло интернета, носителей языка в окружении, а была потеря желания на самообучение - после 5го самоучителя Си, Перл, Фортран и тд. потому что ни кто не мог помочь в далёких сибирских и северных городах и посёлках элементарных вещам и простеньким примерам...


      1. rukhi7
        31.01.2025 09:00

        мне кажется вы совсем неправильно интерпретируете факты. Я как раз начал программировать 30+ лет назад, и точно знаю что отсутствие русскоязычного языка программирования не было проблемой. Русский - это язык межчеловеческого общения как известно, как по мне, он не очень подходит для управления машиной. Кстати есть гипотеза что Пушкин стал мастером русского языка в том числе потому что он знал несколько иностранных.

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


  1. kurpenok
    31.01.2025 09:00

    Спасибо за статью! Посмотрел на Rust под другим углом. Вопрос - не кажется ли Вам, что протест против статики и неизменяемости объектов это слишком жёсткое заявление?

    Я пишу код для ML и в основном работаю на Python. Язык даёт хорошие инструменты для того, чтобы быстро накидать какое-то решение - вызвать нужные классы/методы для реализации своей идеи.

    Однако когда затрагивается вопрос производительности, питон становится бессилен. Конечно, было бы здорово иметь питоновский стиль написания кода и производительность Си, но пока такой возможности нет. А для быстрой работы нужно давать процессору информацию о типах и гарантии о безопасности операций, проводимых с объектами.

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

    P.S. Олимпиадные программисты весьма творчески подходят к решению задач, но код пишут в основном на плюсах :)

    P.P.S. По поводу автогенерации документации соглашусь. В Rust у новичков по типу меня она вызывает дрожь в коленках. Гораздо привычнее небольшой блок на питоне с подписью "Example".

    P.P.P.S. А ещё как сказал мой товарищ: "Всех искусству не научишь. Легче дать жесткий набор правил - так безопаснее".


    1. ednersky Автор
      31.01.2025 09:00

      Вопрос - не кажется ли Вам, что протест против статики и неизменяемости объектов это слишком жёсткое заявление?

      Мне кажется, что повсеместное внедрение типов и отказ от исключений (и goto) - вот это слишком жёстко. При том, что в качестве обоснования к этому идёт серьёзно надуманный пул проблем: дескать иногда пользователь передаёт вместо килограммов квадратные мили и огребает. Да, иногда (именно иногда) такое происходит. Но рассаживать программистов в клетки типов заради этого "иногда" - такое себе.


      1. kurpenok
        31.01.2025 09:00

        Ошибка конвертации и ошибка переполнения, которые привели к серьёзным последствиям.

        История не терпит сослагательного наклонения, но, может быть, помог хотя бы Python type-hinting и проверка Rust на переполнения?


        1. ednersky Автор
          31.01.2025 09:00

          Пара реальных случаев ничего не обозначают. Ещё раз: средний программист (условно) делает 100 ошибок в день. Из них несоответствия типов - не более нескольких процентов


          1. Spyman
            31.01.2025 09:00

            Вы забыли главное - код потом придётся поддерживать. Вот написал ваш коллега модуль, вы его подключили и сегодня все работает. А через год, другой коллега в этом модуля сделал тип возвращаемого значения шире (16 бит на 64 заменил) - а у вас из за этого массив с пустотами вырос на 10гб в озу, но на рабочей машине вы это не увидили т.к. работает. Проблема ушла в прод и повалилась у покупателей продукта, они понесли миллионые убытки и отправили ваш продукт на свалку истории)

            А со статической типизацией - контракт нарушен - не скомпиллировалось и всё


            1. ednersky Автор
              31.01.2025 09:00

              Я помню, что код придётся поддерживать. Однако Вы приводите в примеры маловероятные случаи намеренно отворачиваясь от более вероятных.

              а вероятные у нас ошибки логические: >= вместо >. Количество итераций неверное. Или вообще алгоритм с ошибкой.

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

              здесь снова аналогия: Вы пришли к врачу с ушибом мизинца и раком лёгких, а врач все силы бросил на ушиб мизинца, потому что что делать с раком лёгких он в общем-то и не знает. И лечение вам прописал такое, что всё ваше свободное время теперь ему (лечению) посвящено.

              Что в народе называется: "лекарство горше болезни!"

              вот как-то так же у нас обстоят дела и с типами.


              1. orenty7
                31.01.2025 09:00

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

                Это попросту ложное утверждение. Зависимые типы позволяют математические теоремы доказывать. Посмотрите Software Foundations или plfa


                1. vadimr
                  31.01.2025 09:00

                  Это работает только в определённом классе задач.

                  Как вам поможет типизация в написании программы для игры в шахматы? Теорему, может, какую-нибудь докажете?


                  1. orenty7
                    31.01.2025 09:00

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


                    1. vadimr
                      31.01.2025 09:00

                      Согласитесь, что это очень незначительная по сложности функция в общей задаче.

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


                      1. orenty7
                        31.01.2025 09:00

                        Согласитесь, что это очень незначительная по сложности функция в общей задаче.

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

                        И если не беспокоиться об эффективности, то написать её очень легко, просто перебрать все поля под боем и всё ходы короля.

                        Этого недостаточно. Вот пример позиции в которой любой ход короля оставляет его под шахом, но при этом мата нет, поскольку конём можно снять ладью


                1. ednersky Автор
                  31.01.2025 09:00

                  есть база данных пользователей

                  есть микросервис над ним, выполняющий манипуляции

                  есть микросервис - кеширующий этих пользователей по id

                  есть микросервис - надстройка над предыдущими: ридонли операции он проводит через кеш, ридрайт - через напрямую

                  и в какое место вы впихнёте сюда свои теоремы?


                  1. orenty7
                    31.01.2025 09:00

                    и в какое место вы впихнёте сюда свои теоремы?

                    При достаточном бюджете -- во все.


                    1. ednersky Автор
                      31.01.2025 09:00

                      Вот! И мы приходим, что у бизнеса есть два выхода:

                      • оплачивать труд программистов

                      • оплачивать труд программистов + труд математиков

                      при том, что в первом случае он (бизнес) получает вполне качественный результат, неудивительно, что математикам он зарплаты не платит.

                      и потому математики сбиваются в секту, которая пытается мешать всем жить.


                      1. orenty7
                        31.01.2025 09:00

                        при том, что в первом случае он (бизнес) получает вполне качественный результат

                        Очень качественный, Ariane-5, The DAO и Therac-25 передают привет. И это только из известных. Из менее известных -- откройте любой более-менее крупный проект и посмотрите сколько там багов. Вот вам для примера linux и llvm

                        и потому математики сбиваются в секту, которая пытается мешать всем жить.

                        Удобно бросаться громкими тезисами, особенно если сливаться каждый раз, когда вам указывают на их ошибочность. Вы там в соседнем посте говорили, что функциональщина на понятии "греховность" строится. Уже смогли подтвердить свои слова какой-то статьёй, или хотя бы ссылкой на википедию? Кстати, про википедию и её авторитетность. Получилось разобраться с мутабельностью в эрланге или хотя бы с тем есть ли в ФП переменные? У вас там в ещё соседней ветке спрашивают как так получается, что типы ограничивают творчество и гениальность, а тесты нет.

                        Вы демострируете просто поражающий уровень слепоты ко всему, что не укладывается в вашу картину мира. А то, с каким упорством вы называете остальных сектантами это отличный пример для пословицы про соринку и бревно (ну или про камни и стеклянный дом)


                      1. ednersky Автор
                        31.01.2025 09:00

                        Очень качественный

                        достаточно качественный.

                        а идеального качества достичь банально невозможно.

                        вот вы выбрали один класс ошибок: передача килограмм вместо квадратных метров. Случаются такие ошибки? случаются. Вы предложили вариант, который нет не устраняет - всего лишь минимизирует вероятность таких ошибок.

                        И далее, сколько ваше решение стоит в эксплуатации? Много, очень много.

                        А как часто такие ошибки возникали? Редко, очень редко.

                        итого, внедрение вашего решение ухудшило ситуацию, вместо того, чтобы улучшить.

                        и вы, не желая признавать уже свою ошибку, продолжаете настаивать на ещё большем усугублении ситуации (вчера кто-то мне даже рекламировал применение Rust вместо bash!)


                      1. orenty7
                        31.01.2025 09:00

                        Вы предложили вариант, который нет не устраняет - всего лишь минимизирует вероятность таких ошибок

                        Надёжные (sound) cистемы типов не минимизируют вероятность, они исключают ошибки типизации целиком.

                        И далее, сколько ваше решение стоит в эксплуатации? Много, очень много.
                        А как часто такие ошибки возникали? Редко, очень редко.

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

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

                        О какой ошибке речь? Я пока что всё что я утверждал это:

                        1. Системы типов позволяют проверять логические утверждения

                        2. При достаточном бюджете можно верифицировать все компоненты системы, что вы привели.

                        Где я утверждал, что кому-либо следует внедрять верификацию в свой проект?


                      1. ednersky Автор
                        31.01.2025 09:00

                        Надёжные (sound) cистемы типов не минимизируют вероятность, они исключают ошибки типизации целиком.

                        они не могут исключать ошибки типизации целиком. Ибо если описывать типы абсолютно всего подряд, то программу Вы никогда не закончите. Где-то будете применять стандартные и вот в этом мсете ваша абсолютная заявка стала не абсолютной.

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

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

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

                        поэтому даже если принять Вашу абсолютную заявочку, всё равно: вы боролись с проблемой типов. Вы победили. положили на алтарь этой проблемы двукратное (минимум!) усложнение кода. Решили 1% возникающих проблем, усугубили 99% остальных проблем.

                        И, что характерно, когда Вам на это указывают, когда "на пальцах" разъясняют, когда показывают результаты опроса, вы делаете вид будто "всего этого нет", будто Вы - страус из того мультика.

                        Эх. Бесперспективняк какой-то


                      1. orenty7
                        31.01.2025 09:00

                        они не могут исключать ошибки типизации целиком.

                        Откройте какой-нибудь учебник по теории типов и посмотрите хотя бы Simply Typed Lambda Calculus.

                        Ибо если описывать типы абсолютно всего подряд, то программу Вы никогда не закончите.

                        Во-первых сложность описания типов не связана с надёжностью системы типов. Во-вторых type inference существует не первый год и есть в большинстве мейнстримных функциональных ЯП. Посмотрите алгоритм Хинди-Милнера и в каких языках он используется.

                        Где-то будете применять стандартные и вот в этом мсете ваша абсолютная заявка стала не абсолютной.

                        Буду применять стандартные что? И как от этого сломается надёжность системы типов?

                        ещё раз: ловят они не все ошибки, а убогий процент ошибок, который и без этого не превышал нескольких процентов от всех ошибок.
                        ошибки с типами - мелочь. основные ошибки, которые совершает человек - это ошибки в логике, в стратегии

                        Вы ссылки на SF и plfa из комментария выше не открывали, верно? Мощные системы типов позволяют писать предикаты проверяемые на этапе компиляции и отлавливают, в том числе, ошибки в логике и стратегии.

                        Вы победили. положили на алтарь этой проблемы двукратное (минимум!) усложнение кода. Решили 1% возникающих проблем, усугубили 99% остальных проблем.

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

                        И, что характерно, когда Вам на это указывают, когда "на пальцах" разъясняют, когда показывают результаты опроса, вы делаете вид будто "всего этого нет", будто Вы - страус из того мультика.

                        Ваше объяснение "на пальцах" строится на полном незнании ни теории типов, ни современного ФП. Попробуйте выстроить линию аргументации в которой тезисы более стойкие чем "в ФП всё иммутабельное" и "типы не помогут если перепутать < и <=", которые, очевидно, ложные, о чём вам и в этом посте, и в соседних, не раз сказали.


                      1. ednersky Автор
                        31.01.2025 09:00

                        Посмотрите алгоритм Хинди-Милнера и в каких языках он используется.

                        не буду смотреть.

                        вот итератор/счётчик позиции цикла или этих ваших итераций - это целое число, встроенный тип? Или вы определяете область его допустимых значений и выводите новый тип каждый раз?

                        если первое, то вот вы и попались.

                        если второе, то пограмму вы не допишите.

                        да вы пока и не написали ни одной полезной программы.

                        Буду применять стандартные что?

                        стандартные типы языка.

                        Вы ссылки на SF и plfa из комментария выше не открывали, верно?

                        открыл, взглянул, ничего полезного не увидел.

                        полезного для бизнеса. Для развлечения я книжки читаю.

                        Как кратность усложнения кода считали?

                        сравниваю одинаковые программы на расте и перле. я выше где-то про парсер csv писал.

                        Ваше объяснение "на пальцах" строится на полном незнании ни теории типов, ни современного ФП.

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

                        видите, в эту игру можно вдвоём играть


                      1. IUIUIUIUIUIUIUI
                        31.01.2025 09:00

                        не буду смотреть.

                        Не просто безграмотность, а воинственная безграмотность.

                        вот итератор/счётчик позиции цикла или этих ваших итераций - это целое число, встроенный тип?

                        Подразумевая, что вы имели в виду индекс массива, то это встроенный тип Fin, параметризованный (гошники зажмурились) длиной (все остальные зажмурились) массива. Функция

                        writeAt : Array n a → Fin n → a → Array n a

                        не может выйти за границы вообще никогда, для любого массива любой длины, полученного откуда угодно, хотя Array и Fin являются библиотечными типами.


                      1. ednersky Автор
                        31.01.2025 09:00

                        Не просто безграмотность, а воинственная безграмотность.

                        дело не в безграмотности, а в том, что вы уводите контекст в сторону.

                        и, кстати, приводя в пример автоматический вывод типа, вы сами себе противоречите.

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

                        а теперь ссылаетесь на костыли, позволяющие где-то типы не указывать.

                        здесь, как в том анекдоте, Вам надо определиться: или крестик снять или трусы надеть.


                      1. IUIUIUIUIUIUIUI
                        31.01.2025 09:00

                        дело не в безграмотности, а в том, что вы уводите контекст в сторону.

                        сам отвечает на какие-то свои голоса в голове, не имеющие отношения к комментарию

                        Лол ок.


                      1. orenty7
                        31.01.2025 09:00

                        дело не в безграмотности, а в том, что вы уводите контекст в сторону.

                        Вам по существу уже ответили: аннотации типов и безопасность системы типов это вещи никак не связанные. Причём, что характерно, говорить про аннотации типов вы начали. Хинди-Милнер это мимоходом, просто упомянул, что они даже в мощных системах типов далеко не всегда нужны.

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

                        Итого: есть два утверждения:

                        1. Существует алгоритм вывода типов

                        2. Легче читать код с аннотациями типов

                        В чём противоречие?


                      1. ednersky Автор
                        31.01.2025 09:00

                        В чём противоречие?

                        если легче читать с аннотациями, то вывод типов - это усложнение чтения.

                        нужно что-то выбрать.

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

                        чтобы выбраться из этой ямы аннотаций, вы вынуждены просить компилятор вывести тип за вас, а ещё мучиться с построением АДТ (что компилятор мог бы делать самостоятельно).

                        и всё. где профит? он давно потерян.

                        а в чем была цель? перенести на компилятор какой-то класс ошибок. причём эти ошибки возникали крайне редко (по сравнению с прочими ошибками)


                      1. orenty7
                        31.01.2025 09:00

                        если легче читать с аннотациями, то вывод типов - это усложнение чтения.

                        Вывод типов не мешает наличию аннотаций. Он делает их проставление опциональным, и злоупотребление выводом действительно усложняет чтение кода. Это непротиворечивый набор утверждений.

                        с аннотациями читать сложнее. ибо аннотации в общем случае удваивают количество кода

                        Открыл кусок кода со своего пет-проекта. Аннотаций типов на девять строчек целых две:

                        decodeHandshake :: Parser Handshake
                        decodeHandshake = do
                          expectByte 19
                          forM_ ("BitTorrent protocol" :: String) $ \char -> do
                            expectChar char
                        
                          extentionFlags <- bitunpack <$> nextN 8
                          infoHash <- nextN 20
                          peerId <- nextN 20
                        
                          return $ Handshake extentionFlags infoHash peerId
                        

                        Не похоже на удвоение.

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

                        Вы с дженериками, шаблонами или интерфейсами не сталкивались? Они в мейнстриме лет 30 уже, в 2025-м году нужно постараться найти типизированный язык без чего-то из вышеперечисленного. Но если и правда не сталкивались, вот вам пример обобщённой функции в хаскеле:

                        ghci> :type map
                        map :: (a -> b) -> [a] -> [b]
                        ghci> map (\x -> x + 10) [1..3]
                        [11,12,13]
                        ghci> map (\x -> show x) [1..3]
                        ["1","2","3"]
                        ghci> map (\x -> Just x) [1..3]
                        [Just 1,Just 2,Just 3]
                        

                        ещё мучиться с построением АДТ (что компилятор мог бы делать самостоятельно).

                        Каким боком тут АДТ?

                        перенести на компилятор какой-то класс ошибок. причём эти ошибки возникали крайне редко (по сравнению с прочими ошибками)

                        Даже по вашему опросу (репрезентативность которого я ставлю под сомнение), 25% людей чаще сталкиваются с ошибками типов чем с логическими. Это точно крайне редкий класс ошибок?


                      1. ednersky Автор
                        31.01.2025 09:00

                        Вы с дженериками, шаблонами или интерфейсами не сталкивались?

                        я именно о них и говорю

                        дженерики — второй инструмент после АДТ и третий после автоматического вывода типов и четвертый после interface{}, который пытается вытащить пользователя из той ж..., куда загнали его типами

                        а еще вопросительные знаки в Rust, Box<> и прочий, загромождающий код шлак


                      1. orenty7
                        31.01.2025 09:00

                        я именно о них и говорю

                        О каком, в таком случае, утраивании, учетверении и до бесконечности идёт речь? Вот исходник map, прямо из ghc-internal:

                        map :: (a -> b) -> [a] -> [b]
                        {-# NOINLINE [0] map #-}
                          -- We want the RULEs "map" and "map/coerce" to fire first.
                          -- map is recursive, so won't inline anyway,
                          -- but saying so is more explicit, and silences warnings
                        map _ []     = []
                        map f (x:xs) = f x : map f xs
                        

                        Три строчки, одна из них это аннотация, которую на самом деле, можно выкинуть, и работает с любыми типами. В обычных языках у вас просто цикл по пришедшему массиву больше строчек займёт

                        дженерики — второй инструмент после АДТ и третий после автоматического вывода типов и четвертый после interface{}, который пытается вытащить пользователя из той ж..., куда загнали его типами

                        Дженерики (aka параметрический полиморфизм) и АДТ это часть системы типов, а не отдельный инструмент. Интерфейсы (aka классы типов) в хаскеле выражаются через дженерики и АДТ. При большом желании вы можете руками передавать структуры со всеми нужными методами, и не использовать классы типов, но зачем, если компилятор умеет делать эту работу за вас? Возможость опускать типы в коде это вообще синтаксический сахар, поэтому в чём тут проблема мне неясно


                      1. ednersky Автор
                        31.01.2025 09:00

                        Даже по вашему опросу (репрезентативность которого я ставлю под сомнение)

                        конечно, вы же первый, кто потрудился, чтоб минимизировать его репрезентативность — вы же минус в самом начале поставили, так?

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


                      1. orenty7
                        31.01.2025 09:00

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

                        У вас 17к просмотров, это в три раза больше чем у топовой статьи в лучшем за сутки, и 79 голосов, это где-то как внизу первой страницы лучшего за неделю.

                        и пока статья из сектантских минусов выбиралась

                        37 плюсов, 42 минуса. Возможно, дело в качестве статьи, а не в "функционально-типовом сектанстве"


                      1. ednersky Автор
                        31.01.2025 09:00

                        дело в двух причинах

                        • функциональное сектантство

                        • статья написана при помощи ИИ


                      1. IUIUIUIUIUIUIUI
                        31.01.2025 09:00

                        если легче читать с аннотациями, то вывод типов - это усложнение чтения

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

                        У вас тезис уровня «вы определитесь, или говорящие имена переменных, или i как индекс массива».

                        ибо аннотации в общем случае удваивают количество кода

                        Откуда удвоение-то?

                        а поскольку запрещают писать обобщённые функции

                        Кто запрещает? Почему?

                        а ещё мучиться с построением АДТ

                        В чём мучение?


                      1. vadimr
                        31.01.2025 09:00

                        Ariane-5 управлялся программой, построенной на идеях строгой типизации и даже написанной на специальном ограничивающем программиста и заточенном под доказательство правильности программ языке Ада.


                      1. orenty7
                        31.01.2025 09:00

                        Ада не является языком в котором внутри которого можно выражать теоремы. Это, судя по всему, модифицированный паскаль, и система типов у неё по сравнению с haskell или agda довольно слабая. Плюс в Ариан-5 была отключена часть проверок:

                        ...led to four variables being protected with a handler while three others, including the horizontal bias variable, were left unprotected because it was thought that they were "physically limited or that there was a large margin of safety".


                      1. vadimr
                        31.01.2025 09:00

                        Ада – конечно, не хаскель, но систему управления на хаскеле вы и не напишете. Но ада – статически, сильно типизированный язык.

                        Плюс в Ариан-5 была отключена часть проверок

                        Именно. Получается, что дело-то в прокладке между клавиатурой и монитором, а не в системе типов.


                      1. ednersky Автор
                        31.01.2025 09:00

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

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

                        Вам что непонятно, что мой комментарий был отчасти стёбом на тему игры слов: чистый-нечистый -> религиозное понятие "нечистый" - греховный?

                        Это же ну такая простая цепочка, что если оппонент её не может вычленить, то я вернусь к нему только тогда, когда мне будет не лень.

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

                        если интересно, то вот смысл беседы:

                        1. типы решают весьма-весьма узкий пул проблем

                        2. проблемы с логикой программы типы не решают

                        3. однако предлагается отказываться от комфортных языков в пользу типовых

                        всё это удручает.


        1. vadimr
          31.01.2025 09:00

          Во втором из этих случаев программа была написана на языке Ада, который имеет педантичную донельзя систему типов. Я интереса ради как-то смотрел эту ошибку в исходном коде, там всё было в руках у программиста, но он обошёл имеющуюся в языке проверку переполнения.

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


    1. rukhi7
      31.01.2025 09:00

      Конечно, было бы здорово иметь питоновский стиль написания кода и производительность Си, но пока такой возможности нет.

      Вот проблема-то! Секрет производительности Си это компиляция в нативный машинный код и

      годы потраченные на разработку алгоритмов оптимизации исходного Си кода при компиляции, в двух словах это называется

      оптимизирующий компилятор.

      То есть чтобы Питон был так же эффективен всего то и надо что создать для него:

      оптимизирующий компилятор!

      И возникает вопрос: почему никто даже не помышляет о создании оптимизирующего компилятора для Питона, как вы думаете? (может потому что для него нет стандарта и Питон у всех маленько разный? например.)


      1. frt-ok-g
        31.01.2025 09:00

        Чёто я не помню чтобы у питона было несколько разных реализаций


        1. zzzzzzerg
          31.01.2025 09:00

          Полно на самом деле - PythonImplementations - Python Wiki


        1. rukhi7
          31.01.2025 09:00

          а версии Питона разные есть? а обратная совместимость? Но я не настаиваю что именно это главное (или вообще правильный ответ), но факт в том что нет оптимизирующего компилятора, я как раз спрашиваю: Почему не делают компилятор? Озвучьте вашу версию.


          1. frt-ok-g
            31.01.2025 09:00

            На то, что я имел ввиду ответили выше.

            А именно здесь: https://habr.com/ru/articles/878266/comments/#comment_27859804


          1. Abstraction
            31.01.2025 09:00

            Ну так ровно потому, что эффективный двоичный код и нетипизированный язык - штуки несовместимые.

            def sum(a, b):

            return a+b

            И во что прикажете это компилировать? В add eax, ebx, в call string_concat или во что-то третье?


            1. frt-ok-g
              31.01.2025 09:00

              Самый очевидный вариант перегрузка функций (или как это называется?).


              1. Abstraction
                31.01.2025 09:00

                Мгм.

                def caller(a, b, c, d):

                print sum(a, c)

                print sum(d, b)

                Если у нас... ну пусть пять типов, то предлагаете компилятору сразу генерировать 625 вариантов функции caller? А если типов 50 (в Python вообще-то свои классы можно создавать)?..


                1. frt-ok-g
                  31.01.2025 09:00

                  Здесь на те типы, которые используются отдельные функции (типа sum(int, int); sum(str, str)...), а остальные приводятся к описанным.

                  Например:

                  def sum(a, b):
                    return a + b
                  
                  print(sum("123","123"), # "123123"
                        sum(123, 123), # 246
                        """sum(123, "123") а так вроде ошибка будет
                        Но даже если небудет:
                        ...
                        call strtoint
                        ...
                        call int_sum
                        ...
                        """
                       )
                  
                  int_sum:
                    add edi, esi
                    mov eax, edi
                    ret
                  
                  %macro concat 2
                  ...
                  %endmacro
                  str_sum:
                    concat rdi, rsi
                    mov rax, rdi
                    ret
                  
                  str_arg0 db "123"
                  str_arg1 db "123"
                  
                  mov rdi, str_arg0
                  mov rsi, str_arg1
                  call str_sum
                  push rax
                  mov edi, 123
                  mov esi, 123
                  call int_sum
                  pop rdi
                  mov rsi, rax
                  call print
                  

                  Т. е. перед вызовом функции sum выполняем действия, необходимые для совместимости аргументов.

                  А почему ещё не сделали оптимизирующий компилятор? Слишком много таких нюансов, причём код я привёл несколько упрощённый.


                  1. Abstraction
                    31.01.2025 09:00

                    Ну так прикол в том, что я могу написать десяток-другой своих типов с перегруженным +. Что ещё хуже, к моменту когда компилятор добрался до sum , эти типы ещё могут быть не объявлены. Это примерно как требовать сразу инстанцировать шаблонные функции в C++ для всех наборов параметров, которые могут иметь смысл: комбинаторный взрыв плюс невозможность компилировать программу по частям плюс потенциальные бесконечности (a может быть функцией int->int, int->(int->int), int->(int->(int->int)) и так далее, множество допустимых типов бесконечно):

                    def foo(a) :

                    def bar(b) :

                    return a(b)

                    return bar


                    1. frt-ok-g
                      31.01.2025 09:00

                      Ну так прикол в том, что я могу написать десяток-другой своих типов с перегруженным +

                      Приведите мне пример, где всё не буде спокойно сводиться к простейшим типам


                      1. Abstraction
                        31.01.2025 09:00

                        def sum(a, b):

                        return a + b

                        Вызов должен сделать Int+Int, либо String+String, либо T1+T1, либо T2+T2, либо T3+T3, либо ..., либо T10+T10. Двенадцать разных вариантов (для типов T1-T10 результат вычисляется операциями над полями с разными смещениями, поэтому код заведомо не взаимозаменяем).

                        def foo(a, b, c):

                        if a == 0 :

                        return sum(b, c)

                        return sum(b, a), c

                        Совместное распределение типов имеет 155 разных вариантов. Отдельно обращает на себя внимание вариант (Int, Int, Int), потому что он возвращает то ли Int, то ли Tuple[Int, Int], и как прикажете компилировать код возврата из этой функции?


                      1. ednersky Автор
                        31.01.2025 09:00

                        и как прикажете компилировать код возврата из этой функции?

                        а у нормальных языком под капотом у таких случаев работает нечто, что под капотом выглядит вот прямо так же, как АДТ


                      1. frt-ok-g
                        31.01.2025 09:00

                        Даже если мы вызовем эту функцию со всеми возможными комбинациями типов, у нас переменная a сравнивается с 0, поэтому должна иметь тип int. Логично что её в этот ти надо сначала конвертировать.

                        И, например, мы можем проверять типы и вызывать всё необходимое перед вызовом функции sum.

                        Или сделать "макросы" для конвертирования любого типа в str, int и т. д.


                      1. Abstraction
                        31.01.2025 09:00

                        Даже если мы вызовем эту функцию со всеми возможными комбинациями типов, у нас переменная a сравнивается с 0, поэтому должна иметь тип int.

                        Не должна. Проверка условия [3, "tree", []] == 0 в Python вполне корректна, условие не выполнено.

                        И, например, мы можем проверять типы и вызывать всё необходимое перед вызовом функции sum.

                        Можете, но как только вы перетащили работу с типами во время исполнения - код от компилятора C++ весело помахал вам ручкой и скрылся в голубой дали.


                      1. frt-ok-g
                        31.01.2025 09:00

                        Скрылся или нет, но стандартный питон мы уже заметно обгоним, что тоже немало.


                      1. ednersky Автор
                        31.01.2025 09:00

                        как показывает практика, с этой работой (конвертации) отлично справляется оператор сравнения или прочие математические операторы.


                1. rukhi7
                  31.01.2025 09:00

                  то предлагаете компилятору сразу генерировать 625 вариантов функции caller

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

                  во первых, не просто

                  во вторых, почему то никому не надо.

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


                  1. frt-ok-g
                    31.01.2025 09:00

                    А кода в питоне тип не известен изначально? Даже интересно стало.


                    1. rukhi7
                      31.01.2025 09:00

                      я не знаю, на Питоне не писал, я просто поверил про

                       генерировать 625 вариантов функции

                      на комбинациях из 5-ти типов. Раз говорят что надо все генерировать я так понял (возможно ошибочно).


                    1. Abstraction
                      31.01.2025 09:00

                      def surprise(a):

                      if a==0:

                      return 42

                      elif a==1:

                      return "48"

                      elif a==2:

                      return [4, 2]


                      1. frt-ok-g
                        31.01.2025 09:00

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

                        Например, в rax возвращаем указатель на значение/само значение, а в rdi указываем его тип.

                        И это необходимо только если мы заранее не знаем значение a.


      1. zzzzzzerg
        31.01.2025 09:00

        Ну почему не помышляет то? Есть Cython, есть Nuitka, еще наверное что-то есть не сильно заброшенное. Но когда вы говорите об оптимизирующем компиляторе Питона - надо уточнять что вы имеете в виду. В том же CPython (который является де-факто стандартной реализацией) - есть отдельная фаза компиляции, и как ее не оптимизируй, но генерируемый байткод будет исполняться виртуальной машиной.


      1. Dhwtj
        31.01.2025 09:00

        Оптимизирующий компилятор без статических типов невозможен


        1. ednersky Автор
          31.01.2025 09:00

          ну дык никто у оптимизирующего компилятора типы не забирает.

          речь идёт о том, что 99.9% программистов никогда в жизни не станут писать оптимизирующий компилятор. Соответственно им такого рода инструменты не нужны


          1. AlexAiZzz
            31.01.2025 09:00

            Оптимизирующий компилятор нужен не тем кто его пишет, а тем кто его использует.


            1. ednersky Автор
              31.01.2025 09:00

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


              1. AlexAiZzz
                31.01.2025 09:00

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


                1. ednersky Автор
                  31.01.2025 09:00

                  нету "либо-либо".

                  Есть только набор труда, который должны вложить разработчики компилятора. Но они в последнее время обленились: заставляют пользователей самих обрабатывать ошибки (Rust, Go) или даже мучиться с управлением памятью (Rust) или простановкой типовых аннотаций...


                  1. AlexAiZzz
                    31.01.2025 09:00

                    Ну то есть компилятор Вы никогда не писали, и не курсе какие ограничения накладывают возможности делать разного рода оптимизации. И чего это один из самых популярных Python до сих пор интерпретатор? Народ хает его скорость, но продолжает жрать этот кактус и все больше требует. Совсем, млин, разработчики разленились, не могут в своей стране розовых пони за столько то лет выкатить худо-бедно оптимизирующий компилятор.


                    1. ednersky Автор
                      31.01.2025 09:00

                      Ну то есть компилятор Вы никогда не писали

                      давайте попробуем всёж конструктивно.

                      компиляторы, я действительно не писал, но схожий опыт есть.

                      по работе вот занимаюсь планировщиком/парсером/итп движка SQL для одной из баз данных. но если без личностей.

                      вот пользователь написал программу без типов. Что мешает оптимизирующему компилятору

                      1. преобразовать её в программу с типами

                      2. оптимизировать в своё удовольствие?

                      Предположим, Вы укажете мне, что дескать "компилятор не знает как мой код оптимизировать!". Но вот я беру пишу пример программы на Perl, без типов. Затем прошу Искусственный интеллект переписать её на языке Rust.

                      Он отлично справляется с этой задачей.

                      То есть теоретически мы вполне можем представить себе "умный компилятор", который возьмёт программу, ну скажем, калькулятора, написанного на Perl и соптимизирует её до того, что она будет выполнять все свои функции (вплоть до сделанных логических ошибок), но занимать столько места и требовать столько ресурсов, что будет казаться, что её на ASM написали.

                      В этом месте возникает вопрос: занафига пользователю типы? Как мы выяснили выше ошибки в типах возникают куда реже чем в логике, а следовательно лаконичный код куда лучше загромождённого.


    1. frt-ok-g
      31.01.2025 09:00

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

      Бред, процессор интересуется только размером операнда и тем, допустимый ли используется адрес.

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

      И правильно, там больше свободы.


      1. frt-ok-g
        31.01.2025 09:00

        Ещё, кстати, он проверяет есть ли права на исполнение инструкции.


  1. qrdl
    31.01.2025 09:00

    Прошу прощения, но эта статья автосгенерирована ИИ, я лишь поправил некоторые особенно резкие выражения.

    А это теперь норма на Хабре? Уже не первый раз что-то подобное вижу


    1. flancer
      31.01.2025 09:00

      А что в этом плохого?


      1. DenSigma
        31.01.2025 09:00

        В том, что ИИ не способен к созданию нового.

        Согласно теории информации, никакая программа (а любой ИИ это всего лишь программа), неспособна извлечь больше информации, чем в нее подали. Количество информации после обработки любой программой может только уменьшаться. Вот как обучили ИИ огромным массивом информации - то мы от него и получим.

        Собственно, именно об этом и говорит Маск в вашей ссылке. Количество информации, которое закладывают в ИИ, ограничено, и эта информация подходит к концу.


        1. ednersky Автор
          31.01.2025 09:00

          В том, что ИИ не способен к созданию нового.

          большой вопрос: что такое новое?

          когда художник берёт и смешивает э... пейзаж и геометрические фигуры. У него получается э... кубизм.

          то этот художник создаёт новое? или нет? Кубики и до него рисовали. Ну а чтоб похоже на что-то было - вероятно тоже было.

          Если считать что художник нового не создаёт, то тогда что останется? Признать вот этот современный тренд "рисовать экскрементами" за новизну? Тоже нет?

          Ну, а если Вы о том, что ИИ усредняет. Ну да, и человек усредняет.

          В общем, всё, кажется, относительно.

          PS: А ещё. Вот конкретно эта статья - результат и моих ведь усилий. Текст получился достаточно близок к тому, что я сам бы написал. Правда для этого пришлось приложить вдвое больше усилий, чем если бы я сам его написал.


          1. flancer
            31.01.2025 09:00

            "Это же Клетчатый!" (с)


          1. kalitkinvlad
            31.01.2025 09:00

            Можно сказать, что новое это то, что не детерминируется уже существующим.


        1. AlexAiZzz
          31.01.2025 09:00

          Часто бывает, что нужно не создание нового, а анализ старого. И если ИИ помогает делать обобщения имея большую базу тестов, почему бы и нет. И хотя с содержимым статьи я сильно не согласен, но если ИИ - это не пара тройка уточняющих ему вопросов, то ничего против ChatGPT не имею. Против ИИ, это когда халтурят и свою пятиминутную мысль "Зырьте какое откровение я у ЧатГПТ с трудом выпытал" пытаются выдать за статью. А так согласен с тем, что об использовании ИИ стоит предупреждать сразу, чтоб не возбуждать "аллергию".


        1. flancer
          31.01.2025 09:00

          Я читаю статьи на Хабре для того, чтобы открыть что-то новое для себя. И только лишь. А так как мой персональный опыт очень сильно меньше, чем тот объём информации, на котором обучался ИИ, я могу найти что-то полезное в том, что скомпилировал ИИ из опыта других людей.

          Так-то и преподы в универах из года в год одну и ту же программу преподают. И ничего, каждый год новые студенты их повторы слушают и что-то новое для себя находят.

          IMHO, проблема с постами, написанными как ИИ, так и человеком, одна и та же - как узнать как можно быстрее, знакомая ли для меня эта информация и могу ли я почерпнуть из неё что-то новое.

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

          Так что я не вижу криминала создать, например, промпт на 30-40 тысяч токенов и попросить ИИ уложить смысл в 500 слов. Это, в первую очередь, уважение к читателю. Разумеется, если ИИ не переврал, что я хотел сказать, и я согласен с изложенным.


    1. saag
      31.01.2025 09:00

      "До чего дошел прогресс - вкалывают роботы, а не человек..."(С) Сыроежкин


  1. Abstraction
    31.01.2025 09:00

    Программирование — это искусство. А искусство не терпит правил.

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

    Статическая типизация не спасает от дурака.

    Меня она от себя спасала много раз (следует ли это считать подтверждением что я не дурак?..). От банального "присвоить ID типа A переменной, которая во всём остальном коде интерпретируется как ID типа Б" до "заметить что я использую координаты в неверной проекции" или "это не переведённая текстовая строка, пользователю её показывать не надо".
    И мне чаще приходится сталкиваться с логическими ошибками именно потому, что в функции передаются структуры с типизированными полями, а не массивы "третий компонент обозначает время по Дубаю, четвёртый - число снегоуборочных машин, пятый - бинарное представление PNG с номерным знаком автомобиля".


    1. ednersky Автор
      31.01.2025 09:00

      Контр-тезис: программирование - это овеществлённая математика.

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

      То есть математику можно так же программировать, как и торговлю. А можно программировать, например, игры в покер.

      От банального "присвоить ID типа A переменной, которая во всём остальном коде интерпретируется как ID типа Б"

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


      1. Abstraction
        31.01.2025 09:00

        То есть математику можно так же программировать, как и торговлю. А можно программировать, например, игры в покер.

        Я не говорю о предметной области. Я говорю о том, почему я, написав программу, считаю что она будет делать то, что я задумал. "Мне кажется" - не аргумент (людям кажутся верными очень бредовые вещи, я человек, следовательно то что мне кажется верным может быть бредом). Доказательство - это как раз и есть способ быть более уверенным в том, что ненадёжный ты сделал более надёжную конструкцию. Математика просто учит бить себя по рукам при попытке написать менее надёжно, чем мог бы. Компилятор железный, если он способен поймать мои ошибки - я хочу чтобы он это сделал.

        Будь то игра в покер или автовзвешиватель рыбы, вопрос один и тот же: почему я считаю, что моя программа корректна? Доказательство - это способ строить глобально корректную конструкцию, удостоверяясь в локальной корректности шагов.

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

        Возможно я не вижу цены. Всякое конкретное имя в программе - это конкретный символ в доказательстве, он в любом случае имеет конкретный смысл. Обычно этот смысл может быть выражен типом. Если я не вижу чётких границ этого смысла - это не потому что их нет, это потому что у меня хреновое зрение. В функцию может быть передан неожиданный объект? Значит я тупой, "неожиданный" - это не кодовое слово для имманентно загадочного внешнего мира, это недостаточно строгое моё собственное мышление, которое не учло логически возможный вариант.

        price.parse::<f64>()

        Если price - строка, то в ней может быть "сюрприз" . Я обязан чётко видеть, что именно должна сделать моя функция со строкой такого содержания. (А что если в ней -500? А если произведение приводит к целочисленному переполнению?)
        Здесь можно задать архитектурный вопрос, а не надо ли вынести санацию значений куда-нибудь в район их получения, но локально обязанность ясно понимать поведение функции при каждом физически возможном входе - это самый минимум для того, чтобы хотя бы начинать надеяться, что итоговая программа не является полным, абсолютным барахлом.


        1. ednersky Автор
          31.01.2025 09:00

          "Мне кажется" - не аргумент (людям кажутся верными очень бредовые вещи, я человек, следовательно то что мне кажется верным может быть бредом). Доказательство - это как раз и есть способ быть более уверенным в том, что ненадёжный ты сделал более надёжную конструкцию.

          только во многих областях жизни Вы отлично живёте без доказательств. и это нормально.

          Математика просто учит бить себя по рукам при попытке написать менее надёжно, чем мог бы. Компилятор железный, если он способен поймать мои ошибки - я хочу чтобы он это сделал.

          проблема в том, что она умеет "бить по рукам" в тех случаях, которые не являются типичными для ошибок. А там где человек чаще всего ошибается (в логике) математика ему никак не помогает. Здесь рулит и бибикает старое доброе тестирование и никто пока иного нормального варианта не придумал. Ну, разве что, ИИ доразвивают.

          Если price - строка, то в ней может быть "сюрприз" . Я обязан чётко видеть, что именно должна сделать моя функция со строкой такого содержания. (А что если в ней -500? А если произведение приводит к целочисленному переполнению?)

          можно ведь и другие вопросы задать:

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

          и вот вероятность Вашего "а что если?" так и остаётся ненулевой, но к нему стремится.

          или другой вопрос: а что если этот код упадёт, и пользователь получит "случилось нечто неожиданное". Пожмёт плечами и сделает рефреш.

          При массовом засилии всех этих типов, разве Вы редко видите надписи "случилось неожиданное"?


          1. orenty7
            31.01.2025 09:00

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

            Ну то есть через бюрократический и душащий свободу аналог .parse().unwrap()?


            1. ednersky Автор
              31.01.2025 09:00

              ага, но он внешний, к языку отношения не имеющий.
              вот есть операционные системы - Linux там и ещё какие-то. Ну и есть два способа построения микросервисов: json и ещё какой-то.

              с этим и живём.


              1. orenty7
                31.01.2025 09:00

                ага, но он внешний, к языку отношения не имеющий.

                Валидация json внешняя к языку? Достаточно открыть сайт json-schema и убедиться, что подавляющее большинство валидаторов это просто библиотеки и используются внутри языка


          1. Abstraction
            31.01.2025 09:00

            При массовом засилии всех этих типов, разве Вы редко видите надписи "случилось неожиданное"?

            Я несколько раз пробовал что-то писать на JavaScript, в разных контекстах и по разным поводам. Каждый, каждый раз по достижении пары тысяч строк у меня начинались ошибки "тут integer интерпретируется как массив" (или наоборот). После того как освоил TypeScript, жить стало проще, даже с добавленным геморроем "напиши заголовки для этих пяти библиотек". Поэтому я довольно сильно уверен что если бы у меня не было этой страховки, я бы такой хрени в кодовых базах на сотни тысяч строк видел бы намного больше, чем вижу сейчас.

            а что если пришедшая строка прошла валидацию через jsonschema/иной вариант валидаторов входных данных?

            Тогда price должен быть уже int. Иначе откуда я знаю, что она действительно прошла, а не свалилась с другого логического пути, на который программа попадает при вот такой уникальной комбинации условий? (И такие баги я ловил - когда автор кода почему-то посчитал, что строка прошла через операцию экранирования, а она в каком-то случае нет, и оп-паньки, получился невалидный JSON. Замечу что разделение типа "строка" на типы "экранированная строка" и "неэкранированная строка" позволило бы поймать баг до коммита в main.)

            или другой вопрос: а что если этот код упадёт, и пользователь получит "случилось нечто неожиданное". Пожмёт плечами и сделает рефреш.

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

            Безотносительно этого, "мои ошибки не приводят к серьёзным последствиям" по-моему очень плохое основание чтобы относиться к ошибкам наплевательски. Завтра мне нужно делать меньше ошибок, чем я делаю сегодня. Такое снисходительное похлопывание себя по плечу, "да ничего страшного, чувак" этому не способствует.


            1. ednersky Автор
              31.01.2025 09:00

              Каждый, каждый раз по достижении пары тысяч строк у меня начинались ошибки "тут integer интерпретируется как массив"

              1. берём маловероятное событие

              2. повторяем опыт 1000_000 раз

              3. получаем большое число срабатываний этого события

              Однако как болезнь надо лечить в причинах, а не симптомах, так и проблемы программирования лечить в тех областях где пользователи делают ошибки. А они делают прежде всего ошибки логические и крайне редко ошибки с типами.

              Тогда price должен быть уже int.

              неа, валидатор - такой же микросервис, как и тот, который Вы пишете. он не может менять типы данных внутри json хотя бы потому, что в json всего пять типов данных: строка, число, булево значение и массив с ассоциативным массивом. Всё.

              ну и Int вам не подходит, поскольку как выяснилось выше, страховаться пытаемся от минус (минус) пятисот.

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

              уже лет 15 как я таких программ не встречал.


          1. zzzzzzerg
            31.01.2025 09:00

            А там где человек чаще всего ошибается (в логике) математика ему никак не помогает. Здесь рулит и бибикает старое доброе тестирование и никто пока иного нормального варианта не придумал.

            Да, но нет. Конкурентные алгоритмы верифицируются математическими моделями, а не тестами.


            1. Abstraction
              31.01.2025 09:00

              Тесты вообще сами по себе верифицируют примерно нифига. Они осмысленны только в сочетании с какими-то ожиданиями о реализации, иначе для проверки целочисленного сложения пришлось бы писать отдельно тест sum(2,3) == 5, отдельно тест sum(2,4) == 6 и далее ad nauseam.


            1. ednersky Автор
              31.01.2025 09:00

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


              1. zzzzzzerg
                31.01.2025 09:00

                Спасибо, хороший ответ. Он "многое объясняет".


            1. flancer
              31.01.2025 09:00

              А кто будет формы для веба шлёпать? И какие там матмодели?


              1. zzzzzzerg
                31.01.2025 09:00

                Этим могут заняться программисты, у которых плохо с пониманием прочитанного.


                1. flancer
                  31.01.2025 09:00

                  OK, на первый вопрос вы ответили. Что по матмоделям? Вы же понимаете, что формошлёпы, без руководящей роли, сами их просто не найдут :(


                  1. zzzzzzerg
                    31.01.2025 09:00

                    Вряд ли во мне вы найдете руководителя по этому вопросу, простите.


                    1. flancer
                      31.01.2025 09:00

                      О, тогда, если я правильно понял, что совсем не факт, вы формы шлёпаете руководствуясь мат. моделями? Просто, как шлёпать формы с тестами, я ещё понимаю, а вот как их шлёпать на базе "конкурентных алгоритмов", которые "верифицируются математическими моделями" - тут я провис. Я бы поучился. Просто у меня в опыте веб-форм было много, а мат. моделей для них... да, вообще не было, честно говоря. Selenium пробовал... cypress пробовал..., мат. модели - нет, не пробовал. Это проще?


                      1. zzzzzzerg
                        31.01.2025 09:00

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


                      1. flancer
                        31.01.2025 09:00

                        понапридумывают себе миров, а потом живут там
                        понапридумывают себе миров, а потом живут там

                        Я к формашлёпству перешёл от веб-программирования. Там нет алгоритмов, там нет мат. моделей, но там есть тестирование, и это всё ещё, как ни странно, считается "программированием".

                        Конкурентные алгоритмы... ага, щас!! Ctrl + C / Ctrl + V и не дай бог, где-то забудешь имя переменной изменить.

                        Сначала понаберут математиков, а потом спрашивают с них, как с программистов.


      1. DarkEld3r
        31.01.2025 09:00

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

        Вот я пишу на языке с типами и на проекте принято использовать "strong typedefs". И как мне голосовать, если ошибки типов не доходят до тестирования и тем более пользователей, но именно благодаря языку и нашим усилиям?


        1. ednersky Автор
          31.01.2025 09:00

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

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

          это вот то самое место, где Вы с ошибками типов всё же сталкиваетесь.


          1. DarkEld3r
            31.01.2025 09:00

            Честно говоря, не понял мысль. У меня следующая точка зрения: в строго типизированных языках ситуации когда компилятор бьёт по рукам при попытке сложить строку с числом или передать обычную строку вместо конкретного типа имеющего смысл в нашем домене (пусть будет банальный юзер-нейм) естественно случаются. Но у меня есть большие сомнения, что люди приравнивают эти ошибки, которые, как и прочие ошибки компиляции (вроде незакрытой скобки или забытой точки с запятой), возникают по 100 раз на день, к настоящим багам. Лично я воспринимаю эти вещи как нечто совершенно разное.


            1. ednersky Автор
              31.01.2025 09:00

              Честно говоря, не понял мысль.

              Вы сказали, что не сталкивались с ошибками типов. А я говорю, что если ошибки с типами решает компилятор, то сталкиваетесь вы с ошибками типов тогда, когда разбираетесь с ошибками компиляции.

              Если вы с ошибками типов не сталкиваетесь даже здесь, то компилятор с типами вам снова не нужен (эта функция в нём не используется).

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


              1. DarkEld3r
                31.01.2025 09:00

                Так ведь это ничего не доказывает. Ну и у ошибок сильно разная цена. Одно дело когда проблема ловится прям сразу компилятором - это просто исправляется мимоходом и всё (хотя и тут бывают особые случаи), другое дело - если проблему поймали тестами и третье если ошибка дошла до пользователей.


                1. ednersky Автор
                  31.01.2025 09:00

                  > Одно дело когда проблема ловится прям сразу компилятором

                  это не значит, что проблема не существует. просто эта проблема ловится компилятором.

                  поэтому как бы Вы не отбрыкивались, но статистику о частотности этой проблемы вести можно, говорить о ней можно.

                  тем паче что какие-то языки ради решения этой проблемы и задуманы.

                  а потому опрос, что сверху вполне корректен


                  1. DarkEld3r
                    31.01.2025 09:00

                    Я на 99% уверен, что люди пишущие на статически типизированных языках поняли этот вопрос сильно по-разному. Насколько ценно моё мнение? Да примерно как этот опрос. Ну и я вижу, что ты не намерен дискутировать или что-то прояснить, а только спорить по удобным тебе моментам, обходя неудобные.


                    1. ednersky Автор
                      31.01.2025 09:00

                      я на 99% уверен, что придираетесь Вы к опросу только потому, что его результат противоречит Вашему мнению.


      1. IUIUIUIUIUIUIUI
        31.01.2025 09:00

        не контр-тезис, а моё личное мнение - следствие четвертьвекового опыта программирования: математика не имеет почти никакого отношения к программированию.

        Если честно, я довольно регулярно говорю, что для подавляющего большинства задач (и вакансий) в айти высшее образование и знание математики не нужны. Ну, потому что они правда не нужны, и можно пользоваться системой типов хаскеля без знания теории типов, и можно пользоваться этим вашим Array.reduce в жс без знания того, чем катаморфизмы отличаются от анаморфизмов, и почему reduce через map или filter выразить проблематично, а map или filter через reduce — без вопросов.

        Но при этом каждый раз, когда я вижу такие заявления, как ваши, особенно в контексте воинственных постов «типы не нужны! ограничения и проверки для лохов! Настоящий Мужик программирует без защиты!», у меня возникают сомнения в собственной правоте. Может, математика на уровне хотя бы первого курса факультета прикладной математики (или хотя бы пара семестров матлога) правда нужна, чтобы мозги поставить и сформировать, даже если потом ты ей никогда не будешь [осознанно] пользоваться? Может, айтишечка с математическим цензом была бы более лучшим и приятным местом? Может, я просто не ценю то, что у меня есть?

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


    1. vadimr
      31.01.2025 09:00

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

      Это далеко не всегда теоретически возможно.


      1. ednersky Автор
        31.01.2025 09:00

        я бы сказал: в большинстве случаев невозможно


      1. IUIUIUIUIUIUIUI
        31.01.2025 09:00

        теоретически

        Почему?


        1. vadimr
          31.01.2025 09:00

          Потому что мы можем не иметь полной информации о модели. На данный момент или же в принципе.


          1. IUIUIUIUIUIUIUI
            31.01.2025 09:00

            Тогда как вы пишете эту функцию?


            1. vadimr
              31.01.2025 09:00

              Руководствуясь революционной сознательностью эвристиками.


  1. JBFW
    31.01.2025 09:00

    Раньше программированием занимались те, кому это интересно. Сейчас те, кого научили.


  1. jhoag
    31.01.2025 09:00

    Прошу прощения, но эта статья автосгенерирована ИИ

    Указали бы на это явно и в начале — можно было просто не читать. А так дали повод скрыть вас из ленты.


    1. ednersky Автор
      31.01.2025 09:00

      ну, если Вас это утешит, то чтобы заставить ИИ сгенерить статью, с тезисами которой я был бы согласен, я угробил целую ночь. Ну сам бы написал нечто подобное, добавив, правда, ещё пару пунктов.

      Так что ещё неизвестно, где больше трудозатрат: в труде писателя или в труде оператора ИИ. Как мне кажется, во втором случае их больше. При том, что как система помощи в образовании, ИИ очень хорошо подходит. Тот же Rust изучать с ИИ куда проще, чем по докам.


  1. Dhwtj
    31.01.2025 09:00

    Промт для ленивого человека:

    "Напиши кликбейтную статью о том, как ВСЕ современные языки программирования убили творчество и гениальность в программировании. Упомяни Rust, Go, TypeScript и сравни с Perl. Раскритикуй статическую типизацию, алгебраические типы и иммутабельность. Призови вернуться к 'истокам' и использовать динамические языки для свободы творчества. Я же кросавчег! А что не понимаю то фигня!"

    парочка моих ответов

    Что мешает писать в таком формате? LLM нагенерит на автомате

    /// Парсит строку в объект `Date`.
    ///
    /// Ожидаемый формат строки: `YYYY-MM-DD`, где:
    /// - `YYYY` — год (например, 2025),
    /// - `MM` — месяц от `01` до `12`,
    /// - `DD` — день от `01` до `31`.
    ///
    /// # Примеры
    ///
    /// ```
    /// use your_crate::parse_date;
    /// let date = parse_date("2025-01-31").unwrap();
    /// assert_eq!(date.year, 2025);
    /// assert_eq!(date.month, 1);
    /// assert_eq!(date.day, 31);
    /// ```
    pub fn parse_date(s: &str) -> Result<Date, ParseError> { ... }

    Львиная доля багов — логические.

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

    типы для этого подходят отлично!

    по остальным пунктам устал


  1. Oangai
    31.01.2025 09:00

    Автор, попробуйте FORTH, серьёзно.


    1. ednersky Автор
      31.01.2025 09:00

      я пробовал, но было это давно. Кажется в 1992 или 1993. Я не очень помню что в нём было примечательного. На что я должен был обратить в нём внимание?


      1. Oangai
        31.01.2025 09:00

        полная свобода, вообще никакой типизации, всё в руках программиста.

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

        И да, perl я люблю, основной скриптовый язык для меня.


  1. DenSigma
    31.01.2025 09:00

    Статическую типизацию для того и делали, чтобы в методе не было ахинеи типа "23" + 10. Здесь половина кода не логика приложения, а разбирательство, к какому типу будет приводится это выражение в данном языке - к строке или к числу. Это придется программисту помнить (и уметь про это отвечать на собесах).

    Метод с логикой приложения, это:

    int add(string v1, int v2) {
      int p1 = cast v1 as int;
      int r = p1 + v2;
      return r;
    }

    Но лучше

    int add(int v1, int v1) {
      return v1 + v2;
    }
    ...
    
    r = add(cast "32" as int, 10);
    


    1. ednersky Автор
      31.01.2025 09:00

      Но лучше

      А ещё лучше

      sub add($a, $b) {
         $a + $b
      }

      Да оно может свалиться на тестах (а если тестов нет - на проде), но зато наглядность максимальна. KISS! KISS!


      1. Cheater
        31.01.2025 09:00

        То есть вы считаете нормальным пренебрегать функциональной корректностью ради читаемости?
        Спасибо, это всё, что я хотел знать о динамически типизированных ЯП и неявной типизации.


        1. ednersky Автор
          31.01.2025 09:00

          считаю что читаемый код легче сделать корректным, нежели нечитаемый но код счастливого компилятора


          1. Cheater
            31.01.2025 09:00

            Да, только результатом такого превращения обычно становится код, обложенный велосипедами для валидации. И вы возвращаетесь к исходной задаче с Perl vs Rust, только со стороны перла у вас теперь не однострочник, а уже код гм побольше.


            1. ednersky Автор
              31.01.2025 09:00

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

              ибо логические ошибки компилятор ФП за вас не решит


              1. Cheater
                31.01.2025 09:00

                При чём здесь тесты, я говорю про код самой ф-и. По спеке от него или будет требоваться валидация входной строки или нет. Если не будет, то не надо сравнивать код на Perl без валидации с кодом на Rust, делающим валидацию. Иначе я на Rust напишу без валидации let total = price.unsafe_parse() * quantity.unsafe_parse() (если уж хочется принимать строку, а не сразу принять int и быть свободным от перлопроблем) и скажу что Rust не сильно и длиннее. Если требуется валидация, то как я уже сказал на стороне перла в споре будет участвовать далеко не однострочник.


                1. ednersky Автор
                  31.01.2025 09:00

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


                  1. Cheater
                    31.01.2025 09:00

                    То есть из внешнего мира приходят недоверенные данные, а внутри приложения/бэкенда компоненты радостно общаются между собой всегда корректными данными через всегда неизменный API?

                    Я бы тоже хотел жить в стране единорогов, но увы не могу.


                    1. ednersky Автор
                      31.01.2025 09:00

                      Я бы тоже хотел жить в стране единорогов, но увы не могу.

                      а Вы где живёте? Такси, например, пробовали вызывать? Еду покупать удалённо?

                      Неужто всякий раз, когда Вы пытались это сделать, Вам вместо машины класса Комфорт приезжал карьерный самосвал? Или может быть вместо помидор привозили портвейн?


                      1. Pshir
                        31.01.2025 09:00

                        В Европе несколько раз брал машину напрокат. Разок вместо хэтчбека C-класса давали кроссовер (хэтчбек с декоративными пластиковыми накладками) B-класса. В ресторане в Москве вместо заказанного Цзинь Цзюнь Мэй принесли Принцессу Нури (или что-то в этом роде). Про такси я уж молчу. Это в Москве машины такси стандартизированы. Даже в Московской области это уже не так, и прозрачных критериев нет. А в регионах так вообще: по эконому может приехать старая машина, но зато большая и комфортная, а по комфорту - Логан, но зато новый. И это всё в одном и том же приложении Яндекса. Мир розовых единорогов заканчивается при выезде за пределы МКАДа.


                      1. ednersky Автор
                        31.01.2025 09:00

                        в регионах понятие "комфорт" сдвинуто в какую-то сторону или расширено.

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

                        на частоту сбоев.

                        то что вместо стандарта приедет комфорт - это так задумано. а сбой - это действие так, как не задумано.


                      1. Pshir
                        31.01.2025 09:00

                        Надеюсь, вы понимаете, что с точки зрения пользователя проблема вида «люди, вызвавшие такси, не могут в него влезть, так как габариты машины не соответствуют габаритам людей» является сбоем? Даже если с точки зрения веб-разработчика, сидящего в офисе Яндекса с лавандовым рафом в руках, оно так и задумано. Функция «вызвать комфорт» в регионах имеет недетерминированное поведение, так как строгая типизация существуют только внутри МКАДа, а снаружи её нет. А у веб-разработчика всё прекрасно: интеграционные тесты успешно проходятся каждый день при поездке с работы и на работу. Всегда приезжает комфорт.


              1. IUIUIUIUIUIUIUI
                31.01.2025 09:00

                Вы в прошлый раз так и не ответили — зачем тестами код обкладывать? Тесты ограничивают свободу реализации, тесты придуманы менеджерами для контроля программистов, обложенный тестами код тяжелее менять (приходится обновлять тесты), тесты не ловят ошибки, кроме узких случаев, когда они попадают в ошибочное условие, и тесты занимают кучу времени. Пока вы пишете тесты, я уже вывел продукт в прод и он работает. А если не работает — как вы сами писали, напомните? А, во: ну ничего страшного, поправим и задеплоим снова, невелика беда.


              1. vkni
                31.01.2025 09:00

                ибо логические ошибки компилятор ФП за вас не решит

                Как раз таки многие логические ошибки компилятор найдёт. Классический пример - не используемый конструктор в match with.


          1. ruslan_sverchkov
            31.01.2025 09:00

            Осталось понять что более короткий код не всегда означает более читаемый код, и в целом читаемость понятие субъективное и без четко оговоренных правил его употребление только к срачам приводит) впрочем может быть так и было задумано


            1. ednersky Автор
              31.01.2025 09:00

              Не всегда, это правда. Но, (я так думаю), в большинстве случаев.

              Особенно это актуально для случаев, когда доступ к коду загромождён повторяющимся паттерном, навроде опять же тех же `if err != nil`, которых могло банально не быть в коде.


              1. ruslan_sverchkov
                31.01.2025 09:00

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


                1. ednersky Автор
                  31.01.2025 09:00

                  Я пишу "я так думаю", когда я так думаю. Я так думаю на основе моего опыта работы с кодом. Снова повторюсь, если у Вас есть ссылка на исследование, я её прочитаю.

                  Про типы исследований не было (Ларри Уолла не считаем, он против типов исследование приводил).


              1. Phuysick
                31.01.2025 09:00

                Вы всегда можете принимать err как _ и жить в прекрасном мире паник


                1. ednersky Автор
                  31.01.2025 09:00

                  не получится в _

                  приходится городить Must:

                  func Must[T any](obj T, err error) T {
                      if err != nil {
                          panic(err)
                      }
                      return obj
                  }


      1. Free_ze
        31.01.2025 09:00

        Эта функция не делает ничего полезного, проксируя вызов оператору. Вариант с типами - ограничивает инпут. Это разные функции.

        Наглядность максимальна.

        1. Бросает ли функция ошибки? Если да, то какие и в каких случаях?

        2. Какие операнды туда можно передавать?

        3. Функция возвращает всегда только число или что-то еще?

        Типы лаконично отвечают на эти вопросы, а "наглядность", по утверждениям статьи, требует полотна комментариев с примерами, которые сами по себе ничего не гарантируют и полнотой не обладают.

        Так может проблема в том, что на типы нужно смотреть, как на подсказки, а не как на вынужденный визуальный шум?


      1. DenSigma
        31.01.2025 09:00

        Да, вы сделали НАПИСАНИЕ проще. Ну молодец. Облегчили себе жизнь. А какая когнитивная нагрузка ляжет на тех, кто будет поддерживать и дебажить ваш код, подумали? И первый же вопрос для размышления - как будет реагировать ваш метод, если передать ему строку и число? А если массив и число? А картинку и число? И будет ли работать? Придется читать доки, лепить пробы. И каждый новый программист будет натыкаться на эти вопросы, натыкаться и натыкаться. На сколько человеко-часов вы ограбили свою контору этой "простотой"? "Может свалиться на проде". Я угораю. Во сколько человеко-часов и тысяч (миллионов) рублей выльется ваша "простота"?

        Код не должен быть "простым". Он должен нести минимальную когнитивную нагрузку на тех, кто его читает и поддерживает.


  1. Revertis
    31.01.2025 09:00

    Rust, Go, TypeScript — фабрики по производству посредственности

    Как можно их писать в одном списке вообще? Это совершенно разные языки.

    И, кстати, по статистике 75% или больше как раз ошибок управления памятью и переполнений. И именно Раст мешает их допускать.

    Так что хватит постить дезинформацию, которую новички могут воспринять за чистую монету!


    1. gmtd
      31.01.2025 09:00

      Сало, пирожные и неактивный образ жизни способствуют ожирению

      Их можно в одном списке писать?


    1. ednersky Автор
      31.01.2025 09:00

      по какой статистике? Вашей? моей? Вы результаты опроса выше посмотрели?


      1. Revertis
        31.01.2025 09:00

        По статистике гугла и микрософта. Всё это было тут на Хабре, воспользуйтесь поиском.


        1. ednersky Автор
          31.01.2025 09:00

          понятно. нет статистики, так и запишем.

          зато в опросе выше какая-никакая статистика а есть. и она противоречит Вашим мыслям


          1. Revertis
            31.01.2025 09:00

            Так вы создали тупейший опрос. Конечно там будет тупая же инфа.


            1. ednersky Автор
              31.01.2025 09:00

              Я классифицирую ошибки на два класса: логические (те с которыми не умеет справляться система типов) и типовые (те с которыми она справляться умеет).

              Что здесь не так? Вам не нравится название "логическая".

              Классифицируйте по своему, я приду и проголосую.


              1. Revertis
                31.01.2025 09:00

                Ну так вы неправильно классифицируете. Учите мат-часть, значит.


                1. ednersky Автор
                  31.01.2025 09:00

                  Конструктивный формат диалога: "У Вас это неправильно, правильно вот так!"

                  Деструктивный формат диалога: "У Вас это неправильно. Вы создали тупейший опрос"

                  Что поделать, конструктивное общение становится доступно только с какого-то уровня развития.


                  1. Revertis
                    31.01.2025 09:00

                    А я вас сразу написал, что статистика есть на Хабре. А вы стали отрицать реальность и решили даже не пользоваться поиском. Зачем мне тогда настаивать? Я вам всё дал.


  1. gmtd
    31.01.2025 09:00

    1. Долой тиранию типов! Используйте Python, Perl, Raku — всё, что не душит вашу креативность.

    "Типы" "типам" рознь

    В Java - были прекрасные типы. В TypeScript.. - совсем другие.


  1. Cheater
    31.01.2025 09:00

    Адепты динамической типизации обычно куда-то пропадают, когда речь заходит о:

    • Больших проектах на миллионы строк со сложной логикой. Отличный пример с $price * $quantity кстати. Сегодня всё работает нормально, завтра вы уволились и никто больше не знает что одна из кор библиотек делает небезопасное умножение строк как чисел, а послезавтра разработчик кода 2 уровнями логики выше (и 10 уровнями выше по стеку вызовов) допустит, нет, не поминаемую вами ошибку типизации с передачей строки вместо инта. Просто ошибку. Но в результате этой ошибки в вашу функцию в качестве $quantity придёт пустая строка, которую Perl спокойно интерпретирует как 0 и вернёт 0. И пустая строка будет приходить не гарантированно, а в определённой фазе луны и в ситуации, не покрытой тестами. Удачи с отладкой.

    • Разработке библиотек, т.е. о ситуации где вы не знаете в каких условиях будет применяться ваш код и у вас не будет права делать предположения о важности или неважности некорректной работы вашей программы на некорректных входных данных.


    1. JBFW
      31.01.2025 09:00

      Хм, не вижу проблемы с п.1.

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

      И тестировщиков которые не подумали что вместо "3.56" юзер может забить туда "бебебе" и не проверили это.

      Ну то есть как раз по сути статьи: защита от криворуких разработчиков.


      1. Cheater
        31.01.2025 09:00

        У вас мир такой простой, разработчик передал не валидную строку значит дурак. У меня в примере не "бебебе", а пустая строка, возникшая в результате ошибки возможно где-то посреди стека функций. Она может возникать в результате ввода определённых данных (валидных с ТЗ вызывающего и его кода).


        1. ednersky Автор
          31.01.2025 09:00

          у обработки ошибок есть много стратегий. Игнорирование ошибок - одна из таковых, причём, в ряде случаев эта стратегия может работать лучше обработки.

          ещё есть ерланговый подход "пусть падает - перезапустим!"

          ну и насаждаемый в современное время "давайте обрабатывать всё!", но этот подход в массы не заходит: среднестатистический код настолько часто делегирует обработку ошибок "выше", что в Rust даже для этого оператор придумали.


          PS: Вот, только что в соседнем треде писал коммент:

          давайте вот об ошибках поговорим.
          вот заставили пользователей вместо исключений обрабатывать ошибки.

          но что делает среднестатистический код с ошибками?

          правильно: делегирует их выше!

          if err != nil {
            return nil, err
          }

          Причём этот паттерн (делегирование выше) настолько частотен, что в Rust для него даже придумали специальный оператор - вопросительный знак.

          Хорошо сделали? Ну типа посыл такой: заставить пользователя обрабатывать ВСЕ ошибки и думать обо всех ошибках.

          Ну ок. Вы так сделали, заставили.

          Но попробовать подумать об ошибках вы, увы, даже не пытались.

          возьмём, например, условный стек вызовов:

          foo(bar(baz(42)))

          Допустим в baz ошибка, которую мы поймали и обработали в foo.

          В чём здесь может быть проблема? А проблема в том, что источником ошибки может быть неверный код в функции bar. А когда пользователь смотрит на текст ошибки выброшенный функцией foo, он bar и baz не видит.

          а раньше с исключениями у него хотя бы был стек.


          1. Cheater
            31.01.2025 09:00

            ЯННП. Передавать объект "ошибка" через 100 уровней наверх, и обрабатывать его там, где теряется контекст ошибки, - антипаттерн. Если только высокоуровневая функция foo способна понять, что данные неверны, а bar и baz не способны, то какова альтернатива обработке этой ошибки в foo? Если её можно идентифицировать в bar, то почему foo а не bar занимается обработкой? Не обрабатывать делегированные ошибки - плохо. Как всё это дискредитирует оператор "?" я не понимаю. Исключения же вообще ортогональны обсуждению.


            1. ednersky Автор
              31.01.2025 09:00

              Передавать объект "ошибка" через 100 уровней наверх - антипаттерн

              Стоп!

              это не антипаттерн, а наиболее часто встречающийся паттерн.

              он настолько часто встречающийся, что Rust ради него даже целый оператор залепили.

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

              исключения - это просто способ обработки ошибочных ситуаций.

              Вы можете обрабатывать их сами вписывая if err != nil (или его аналог в другом языке) по месту, а можете делегировать это компилятору, который "напишет такой же код за Вас".

              а больше ничем исключения от ошибок не отличаются.

              Каждый раз выходя из текущего фреймстека нужно потрогать GC: позвать там всякие defer'ы и проч.


            1. Dhwtj
              31.01.2025 09:00

              Передавать объект "ошибка" через 100 уровней наверх, и обрабатывать его там, где теряется контекст ошибки, - антипаттерн

              выброс исключения делает то же самое - лови его на 100 уровней выше


    1. ednersky Автор
      31.01.2025 09:00

      я участвовал на практике в двух больших проектах, работающих исключительно на динамической типизации, описываемых Вами проблем не встречал (то есть встречал, конечно, но по сравнению с прочими — в следовых количествах)

      вот к доктору пришёл больной с двумя диагнозами:

      • раковая опухоль в почке

      • ушиб мизинца на ноге

      и доктор предлагает ему годичный курс физиотерапии для мизинца, а еще такой же годичный курс психологической помощи (в хорошем психсостоянии вероятность ещё раз неудачно споткнуться уменьшается)

      а рак, ну что тот рак? доктор его лечить не умеет, потому забивайте на рак, меняйте свою жизнь, чтоб мизинцу ноги жилось хорошо...

      вот какая-то такая аналогия с внедрением типов у нас


  1. Vitaly83vvp
    31.01.2025 09:00

    Вопрос выбора ЯП зависит от многих факторов. Сравнивая Perl и Rust, нужно брать во внимание и то, как будет использоваться код. Например, программу на Go/Rust можно спокойно запустить на другой машине без необходимости установки дополнительного ПО. С Perl такое не прокатит.

    Хотя, в плане документации, согласен - раньше писали гораздо удобную документацию. Сейчас приходится искать дополнительные материалы.

    Когда начинал писать на Go, увидел, что синтаксис значительно отличался от привычного. Во всех других языках было что-то от C, поэтому особых сложностей (кроме PHP с $ для переменной) не возникало. Rust пока только посмотрел, но что-то написать ещё не пробовал.

    С тем, что новые ЯП накладывают всё больше ограничений, согласен. Поэтому, перед тем как что-то разрабатывать, нужно чётко себе представлять как и где будет использоваться это приложение: GUI/Console, Client/Server, Mobile/Desktop и много другого.

    Если какой-то ЯП действительно плох, то он не будет развиваться. Если развивается, нужно "прощупать" его потенциал и изучить.


  1. onyxmaster
    31.01.2025 09:00

    Сначала путают динамическую, статическую, сильную и слабую типизацию, а потом конкатенируют строки с коллбеками…


  1. fiego
    31.01.2025 09:00

    Мне понравилась, очень задорная статья. Особенно: "Пора назвать вещи своими именами: мы променяли гениальность на мнимую безопасность, а свободу — на кандалы статических проверок". Ну и в целом довольно провокационно-весело.

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

    Примеры с Perl прикольные, ЯП действительно особенный. Высказывать своё мнение про динамические/статические типы не вижу смысла, всё давно уже обговорено на сто тыщ пятьсот миллионов раз.


    1. ednersky Автор
      31.01.2025 09:00

      Спасибо за отзыв, но, увы, даже тег "пятничное" не помог. адепты типов слили в минуса :)


  1. Free_ze
    31.01.2025 09:00

    Где примеры?

    Так почему вы их не написали?) В стандартной библиоткеке, например, они есть. В случайном популярном стороннем крейте - тоже есть. Так в чем проблема?

    Возвращает Result<i32, ParseError> (ведь вы обязаны обработать даже апокалипсис)

    Но ниже без проблем применяется unwrap ничего не обрабатывая. Выходит, не обязаны.

    _ => panic!("Вы не обработали этот случай, потому что Rust вас ненавидит"),

    Итог: АТД — это статики пытаются имитировать свободу динамических языков. Получается как всегда: сложно, многословно, и всё равно небезопасно.

    Если хотите игнорировать проблему, то зачем пишите панику? Язык этого не требует.
    Если же нужна надежность, то обрабатываете явно все ветви, ветка по discard pattern (_) не потребуется.


  1. undersunich
    31.01.2025 09:00

    Все по делу! Автору уважение за смелость! Только в современном мире подход - берите другой язык и получайте удовольствие не работает.Выбрать язык и самому на нем работать можно только на своем проекте при неограниченной финансовой подушке.Когда вы приходите на работу (на новый проект) Вы всегда подстраиваетесь для того что бы .... выжить Поэтому проблемы описанные в статье правильные но увы языки мы (как ни странно) не выбираем а подстраиваемся под глубинные течения развития технологий


  1. icecube092
    31.01.2025 09:00

    Мда, старый не значит мудрый


  1. DarkEld3r
    31.01.2025 09:00

    Добро пожаловать в ад автосгенерированной документации! Rust-крейты похожи на налоговые кодексы:
    ..
    Где примеры? Зарыты где-то между #[derive(Debug)] и impl FromStr. Чтобы понять, как использовать функцию, вам понадобится докторская степень по расшифровке типов.


    Ну зачем так нагло врать-то? Смотрю на документацию parse и на описание трейтаFromStr - и там и там примеры есть. Более того, описывать входные параметры и результат в расте не принято. Как раз потому, что мы видим тип, на которой можно нажать и перейти, если что-то не понятно. А "input - входная строка" для параметра типа input: &str писать как-то бессмысленно.


  1. funny_falcon
    31.01.2025 09:00

    Забавно: я - «опытный разработчик», но ещё не дорос до Rust.

    При этом не далее как на новогоднем корпоративе имел беседу с девопс-ом, который признался, что в последнее время предпочитает писать «скрипты» на Rust вместо Bash, Perl или Python, т.к. получается «понятнее, компактнее и производительнее».

    Получается, «разруха в головах, а не в сортирах».


    1. ednersky Автор
      31.01.2025 09:00

      Вот уж точно разруха! Дев-опс. Rust вместо bash и Python. Компактнее.

      и дев-опс, которому важна производительность bash.

      какая-то иная планета прям


  1. Pubert
    31.01.2025 09:00

    Говорите, "25"+10=30 - это хорошо, а потом советуете python?) Ха!

    P.S. не путайте строгую и статическую типизации


    1. ednersky Автор
      31.01.2025 09:00

      Python в советах из серии "лучшее из возможного/популярного"


  1. AndrewT2
    31.01.2025 09:00

    Всегда думал, что perl делал человек далекий от it.


    1. ednersky Автор
      31.01.2025 09:00

      Ларри лингвист, именно поэтому у него получился язык наиболее приближенный к человеческому


  1. 9241304
    31.01.2025 09:00

    Надо же, заморочился. Такой манифест для оправдания говнокода придумал)


  1. Proscrito
    31.01.2025 09:00

    О, боюсь человечество ушло не туда гораздо раньше. В доисторические времена было намного больше свободы и меньше бюрократии. Собственно, ее вообще не было, для нее нужна письменность. При этом каждый день испытывал твои способности на прочность, требуя определенно выдающихся способностей для банального выживания. Но затем кто-то изобрел лень и начался прогресс. Который сейчас достиг такого уровня, что некоторая часть и без того несложной работы делает себя сама. А свобод стало на порядок меньше. Все эти правила, уголовный кодекс обратно же... Могу понять, почему некоторым охота повернуть время вспять. Чтобы вновь героически превозмогать, изобретать, творить, как в старые добрые. Увы, не в то время родились.


  1. alabamaa
    31.01.2025 09:00

    Во многом согласен с автором, но есть два возражения:

    1. Почему JavaScript отсутствует в компании свободолюбивых языков, также и в связке с WebAssembly ?

    2. Строгая типизация не препятствует свободе творчества, яркий пример тому - С++.


    1. Proscrito
      31.01.2025 09:00

      В си шарпе можно работать с указателями, в том числе не типизированными типа void*. А пометив кусок кода кейвордом unsafe можно манипулировать памятью напрямую, получать указатели на области памяти и творить с ними любую чертовщину. Преобразовывать любые типы к любым типам, например. Впрочем, и без него можно, и я знаю еще как минимум два трюка для этого. Можно менять данные в immutable типах, например строках. Можно отключить проверку переполнения кейвордом unchecked. Можно работать с областью памяти как с нетипизированным массивом неопределенной длины при помощи span'ов. Это разумеется та область, которую большинство дотнет девов не знают, но она есть, абсолютно легальна и из коробки есть еще и миллион готовых хэлперов для работы с ней. По моему опыту большинство разработчиков использует лишь часть возможностей языка из тех, о которых знает, а знает лишь часть из тех, которые в нем есть. Да и знает обычно поверхностно. Этого вполне достаточно для успешного коммерческого использования. Но не для науки и искусства конечно.

      Широкие возможности не мешают творчеству, только наоборот. Это дополнительные цвета в палитре. Но нужно разумеется хорошо знать используемую палитру, набор кистей и технологичный мольберт. А можно рисовать охрой на стене пещеры, считать это свободой и презирать художников, которые "ограничены" холстом и зависимы от производителей.


  1. meonsou
    31.01.2025 09:00

    На самом деле, не смотря на то, что статья явно байт, я полностью согласен с тезисами про многословность и неповоротливость статической типизации (в мейнстримных языках).

    Особенно вот с этим:

    let total: f64 = price.parse::<f64>().unwrap() * quantity.parse::<f64>().unwrap();  
    

    Примерно поэтому раст для меня совершенно невыносим.

    Однако, в общем случае я не согласен разменивать гарантии от компилятора на гибкость и выразительность, я правда полагаюсь на эти ошибки и они часто выручают меня. Не говоря уже о том, что дело не только в ошибках. Почти весь современных developer experience вроде автодополнения и подсказок невозможен без тщательного анализа программ, которому крайне плохо поддаются динамически типизированные языки. Одно только отсутствие интеллисенса является поводом не писать на очередном perl или lua вообще. Это огромный удар по моей продуктивности как разработчика.

    Но самое грустное в этой истории, пожалуй, не то, что придётся в очередной раз писать на очередной джаве или расте. Грустно что на самом деле теория языков программирования уже давно решила большинство проблем, обозначенных в статье. И решила она их не вчера, а десятки лет назад. Но мейнстримые языки программирования в упор не хотят замечать эти разработки.

    Подобные поиски действительно удобного языка программирования привели меня к ML (Meta Language, а не Machine Learning) и его современным диалектам вроде OCaml и F#. Я до сих пор считаю что, за мелкими исключениями, это идеальный язык программирования.

    Вот, взгляните:

    let add a b = a + b
    

    Никаких типов не указано, всё максимально просто и понятно (за исключением непривычного для мейнстрима синтаксиса). При этом типы существуют и полностью выводятся автоматически.

    При этом в ML не нужно никаких IO монадов. Хочешь писать императивно с изменяемыми переменными и циклами? Так и пишешь:

    let count n =
      let i = ref 0 in
      while !i < n do
        Printf.printf "%d\n" !i;
        i := !i + 1
      done
    

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


    1. IUIUIUIUIUIUIUI
      31.01.2025 09:00

      При этом типы существуют и полностью выводятся автоматически.

      Это потому что у вас rank-n-полиморфизма, GADT и прочего нет, а оно бывает полезно, мягко скажем.

      Если же вы конкретно про этот пример, то для подобных let-байндингов (без нетривиального паттерн-матчинга, и так далее) не нужны аннотации даже в языках с принципиально неразрешимым выводом типов, вроде агды или идриса.

      При этом в ML не нужно никаких IO монадов.

      Как будто монады — это что-то плохое.

      Хочешь писать императивно с изменяемыми переменными и циклами?

      Теряешь возможность локально рассуждать о коде.

      Я занимался аудитом кода на окамле, это ад. Код на хаскеле по сравнению с ним — это небо и земля.

      При этом чем это принципиально лучше

      count n = do
        i ← newIORef 0
        whileM_ ((< n) <$> readIORef i) $ do
          print =<< readIORef i
          modifyIORef' i (+ 1)

      непонятно. Кроме того, что синтаксис чуть тяжелее, это да, но это как раз стимулирует сделать нормально для кратких примеров:

      count n = mapM_ print [0 .. n - 1]

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


      1. vkni
        31.01.2025 09:00

        Я занимался аудитом кода на окамле, это ад.

        Да ладно, после C++ отлично рецензируется и понимается.

        У Хаскеля проблема в том, что он уже 30 лет research language. С соответствующим культурным кодом. Хотя, как говорится, "вы 50 лет занимаетесь полупроводниками, пора бы уже к полным проводникам перейти!".

        В OCaml хотя бы можно быть уверенным, что если написал программу на stdlib, то через 20 лет она будет почти полностью компилироваться на trunk.


        1. IUIUIUIUIUIUIUI
          31.01.2025 09:00

          У Хаскеля проблема в том, что он уже 30 лет research language. С соответствующим культурным кодом. Хотя, как говорится, "вы 50 лет занимаетесь полупроводниками, пора бы уже к полным проводникам перейти!".

          В OCaml хотя бы можно быть уверенным, что если написал программу на stdlib, то через 20 лет она будет почти полностью компилироваться на trunk.

          Некоторая ОС с девизом stable API is nonsense вполне успешно живёт что на мобильниках, что на серверах, так что не думаю, что проблема именно в этом.


          1. vkni
            31.01.2025 09:00

            У этой ОС есть очень даже фиксированный API под именем POSIX.

            Нет, только матом, только им описывается обратная совместимость Хаскеля! А то, что милые люди из WellTyped поломали систему сборки? Я постарался донести до ряда людей (Зубин, Гамари) простую мысель, что OCaml легко проходит через сцену любого копроративного театра безопасности за счёт того, что bootstrap компилятор поставляется в байткоде. Но, блин, там изначальная задача - держать GHC в вечной альфе.


            1. IUIUIUIUIUIUIUI
              31.01.2025 09:00

              У этой ОС есть очень даже фиксированный API под именем POSIX.

              Модули ядра ты пишешь через POSIX?

              Нет, только матом, только им описывается обратная совместимость Хаскеля!

              А мне норм. Я как-то раз спокойно в 2019-м году взял компилятор, написанный мной в начале 2017-го и с тех пор не обновлявшийся, поменял в stack.yaml резолвер на актуальный stackage lts, потратил где-то 10 минут на выковыривание устаревших методов из кодовой базы в несколько тыяч строк, и всё после этого сразу заработало (получив заодно где-то ЕМНИП 20% прироста производительности тупо за счёт обновления компилятора и библиотек).

              А то, что милые люди из WellTyped поломали систему сборки?

              Эээ, я тут открыл для себя ghcup и последние года три получаю свежий ghc оттуда, так что не в курсе — а что там поломали?

              Я постарался донести до ряда людей (Зубин, Гамари) простую мысель, что OCaml легко проходит через сцену любого копроративного театра безопасности за счёт того, что bootstrap компилятор поставляется в байткоде.

              Не видел ни одной компании, где отсутствие бутстраппинга являлось бы ключевым препятствием перед корпоративной красной лентой. Основная сложность в нашей общей компании-то была ЕМНИП в том, чтобы убедить клоунов актёров из этого театра дать blanket permission на либы в hackage.

              Кстати, как там gcc нынче бутстрапится, и кому это мешает?


              1. vkni
                31.01.2025 09:00

                Модули ядра ты пишешь через POSIX?

                Далёк я от них!

                Я как-то раз спокойно в 2019-м году взял компилятор, написанный мной

                Вот, написанный кем! А в нормальном кровавом ынтерпрайзе оно написано совсем не тем человеком, которому надо обновлять. И всего-то 2 года прошло.

                Я на прошлой неделе взял что-то подобное, написанное мной на OCaml'е, 10 лет назад. Оно скомпилировалось с предупреждениями.

                Основная сложность в нашей общей компании-то была ЕМНИП в том, чтобы убедить клоунов актёров из этого театра дать blanket permission на либы в hackage.

                Это да. Я, кстати, сейчас главный хаскеллист конторы (как оно низко пало!!! :-) ). И я таки один раз этот blanket permission получил. Но это была конкретная проблема...


    1. ednersky Автор
      31.01.2025 09:00

      ну вот, научились выводить типы из контекста "что имел в виду пользователь"

      осталось окончательно снять с пользователя возню с типами вообще.


      1. vkni
        31.01.2025 09:00

        Зачем снимать с пользователя возню с типами? Типы - это избыточная информация в программе, позволяющая построить "взгляд на программу с птичьего полёта".

        То есть, естественная последовательность нормальной разработки программы это спираль из

        1. Сбора требований.

        2. Построения наброска программы на псевдокоде из типов и аннотаций функций/модулей.

        3. Реализация.

        4. QA

        На первых витках спирали вы бегаете в основном между пунктами 1-2, на последних - в основном между 3-4.

        А типы тут позволяют относительно легко закодировать значительную часть функциональных требований.


        1. ednersky Автор
          31.01.2025 09:00

          Зачем снимать с пользователя возню с типами? Типы - это избыточная информация в программе, позволяющая построить "взгляд на программу с птичьего полёта".

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

          Построения наброска программы на псевдокоде из типов и аннотаций функций/модулей

          не из типов, а БЕЗ типов и аннотаций.

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

          Я вот сделал набросок парсера CSV на 5 строк кода на Perl затем попросил ИИ переписать его на Rust: получил 25 строк кода на Rust. Если пропустить через тесты, то этот код делает одно и то же. Но на Perl это всего 5 строк кода. То есть, если бы разработчики компиляторов не ленились, они могли бы нормально компилировать что угодно: хошь питон, хошь какой угодно другой язык.

          и рано или поздно так и будет: просто сейчас ИИ - это ферма из сотен серверов, но когда-нибудь она редуцируется до программы в ноутбуке.


          1. IUIUIUIUIUIUIUI
            31.01.2025 09:00

            Так как вы сами писали, что не терпите бездоказательных утверждений, то я посчитаю их в этом комментарии ради лулзов:

            затем, что это естественно для человека НЕ оперировать типами

            1

            И ему пофиг что считать. Типы становятся не важны.

            2 [альтернатива: человек генерализирует до общего типа «считабельные объекты», а неспособные в генерализацию люди не осиливают счёт за пределами палочек]

            аннотации нужны только компилятору

            3

            просишь ИИ переписать код без аннотаций в код с аннотациями и ИИ отлично с этим справляется

            4

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

            5

            и рано или поздно так и будет

            6


            1. vkni
              31.01.2025 09:00

              Я, если честно, просто воспользовался моментом, чтобы изложить свои мысли по-поводу архитектуры. Переубедить @ednersky нельзя, т.к. он явно не является ботом, и слишком много написал комментов, чтобы не рассматривать переход на другую сторону как "потерю лица". Хотя, конечно, это смешно.

              Где-то пробегала заметка о том, что composability требований к софту значительно выше, чем composability деталей этого софта. То есть, значительно проще написать, что программа должна делать А и Б, чем реализовать это (при условии, что требования А и Б написаны + написаны подпрограммы, реализующие А и Б).

              А требования к софту часто напрямую выражаются в типах. Пусть эти типы и очень сложны, и даже невычислимы. Отсюда выходит эффективность type-driven development.


              1. ednersky Автор
                31.01.2025 09:00

                А требования к софту часто напрямую выражаются в типах. Пусть эти типы и очень сложны, и даже невычислимы.

                именно невычислимы. но адепты типов стремятся это сделать. Вон соседняя ветка про ООП головного мозга. Там адепты ООП делают ООП чтобы задать опции поведения ООП, который будет управлять ООП, который запустит ООП из main, которую тоже нужно запхать в класс, а не просто запускать as is.

                Вот вы с этими типами повторяете ровно тот же путь, просто ООП у вас заменён на типы.

                И, кстати, типы и ООП во многом синонимы. И вы должны были бы оппонировать автору статьи. Но нет - вам кажется, что вы не такие.

                Отсюда выходит эффективность type-driven development

                не выходит.

                типы, как один из инструментов TMTOWTDI, приводящему к KISS (или на худой конец - стабильности) - хорошая вещь.

                но вы как те персонажи соседнего треда, хотите довести всё до абсолюта, чтобы получить абсолютную хрень


                1. IUIUIUIUIUIUIUI
                  31.01.2025 09:00

                  именно невычислимы. но адепты типов стремятся это сделать.

                  Я боюсь, вы даже не понимаете, в каком смысле тут упоминалась невычислимость. Это, конечно, очень смешно.

                  И, кстати, типы и ООП во многом синонимы. И вы должны были бы оппонировать автору статьи. Но нет - вам кажется, что вы не такие.

                  Не все базисы, по которым раскладывается intrinsic-сложность систем, одинаково полезны. ООП — неудачный базис [в большинстве задач, и в подавляющем большинстве задач, с которыми сталкивался лично я]. ФП (в смысле типов) — куда более удачный базис [снова в большинстве задач].


                  1. vkni
                    31.01.2025 09:00

                    Я боюсь, вы даже не понимаете, в каком смысле тут упоминалась невычислимость. Это, конечно, очень смешно.

                    Кстати, прорабатываю эти самые refinement types для своей задачи, там реально в полный рост невычислимость местами. На задаче type inference, а не задаче type checking. Просто в конечном итоге границы фазовых областей описывают некоторые феноменологические полиномные интеполяционные формулы, от которых, кажется, даже не вычислить обратные в радикалах. Но это, в принципе, и не нужно.

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

                    То есть, получается, что теория типов даёт framework, внутри которого приходится залезать в довольно экзотические места. Зато Пирс и прочие саксаулы нарисовали какую-то карту.

                    В общем, очень полезная эта ваша атипичная деятельность в сельском хозяйстве. Но надо подработать напильником.


                    1. IUIUIUIUIUIUIUI
                      31.01.2025 09:00

                      На практике я бы считал приближённо и в интервальной арифметике — всё равно все данные с погрешностями. А там уже и формулы расслабить можно, и полегче будет.

                      Но, опять же, я ничего не знаю о предметной области.


    1. vkni
      31.01.2025 09:00

      Примерно поэтому раст для меня совершенно невыносим.

      В вашем коде, что характерно, unwrap - это с практической точки зрения совершенно небезопасный код. В обычном десктопном приложении, срабатывание panic абсолютно эквивалентно по последствиям SIGSEGV, что бы там кто ни говорил.

      И всё ещё никаких явных типов.

      В результате без IDE это полный Пэ. Посмотрите какие-нибудь старые простыни в ocaml/typing - это же вообще непонятно, кто кого и зачем. Хаскель, всё-таки, очевидно, йазыг следующего поколения.

      Проблема Хаскеля в том, что он не промышленный, а шершер. По-поводу половины решений WellTyped и SPJ, увы, выражаться можно только матом.


      1. meonsou
        31.01.2025 09:00

        В результате без IDE это полный Пэ.

        От части да, но на самом деле я не особо понимаю претензий к тому что ЯП неудобен "без иде". С таким же успехом можно говорить что он неудобен на бумаге или на глиняной табличке. Не считаю это недостатком, так как не пользуюсь ни табличками, ни блокнотом.

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

        Полагаться на иде так же нормально, как полагаться на компилятор.


  1. Dhwtj
    31.01.2025 09:00

    Немного LLM в обратную сторону

    Извините, в один комментарий не влезло


  1. Dhwtj
    31.01.2025 09:00

    Хватит писать на динамических языках: Крик души разработчика, уставшего от боли!

    Да, я знаю, динамические языки – это круто, быстро, модно, молодежно. Python, JavaScript, Ruby – они как быстрая еда в мире программирования. Схватил, набросал, вроде работает! И на первых порах это действительно кажется волшебством. Но, черт возьми, когда дело доходит до серьезных проектов, эта "магия" превращается в настоящий ад!

    Хватит уже обманывать себя! Хватит строить карточные домики на песке, которые рушатся от малейшего дуновения ветра! Динамическая типизация – это мина замедленного действия, заложенная под ваш проект!

    Вспомните это чувство: вы часами отлаживаете код, ломая голову над ошибкой, которая, как вам кажется, просто невозможна. И вот, после долгих мучений, вы с ужасом понимаете, что допустили опечатку в имени переменной! В динамическом языке, где никто не следит за типами, эта мелочь превращается в катастрофу! Компилятор статически типизированного языка заорал бы на вас еще на этапе написания кода! Но нет, динамика – это же "свобода"! Свобода страдать и тратить драгоценное время на исправление глупых ошибок!

    Вот вам пример из жизни: Представьте себе функцию, которая должна принимать число и возвращать его квадрат. В динамическом языке вы можете случайно передать ей строку. И что произойдет? В лучшем случае – ошибка в рантайме, в худшем – неожиданное и непредсказуемое поведение программы! В статическом языке компилятор просто не позволит вам скомпилировать такой код! Он скажет вам: "Эй, друг, ты пытаешься сложить банан с апельсином! Это не сработает!" И спасибо ему за это! Спасибо за сэкономленные нервы и часы отладки!

    Динамические языки – это как дом без фундамента. Вы можете построить его быстро, но он будет шатким и ненадежным. Любое изменение в коде – это русская рулетка! Вы никогда не знаете, что сломается в другом месте. Рефакторинг в динамическом языке – это хождение по минному полю! Вы боитесь каждого шага, потому что знаете, что в любой момент может рвануть!

    А как насчет читаемости кода? В динамическом языке, чтобы понять, какого типа данные ожидает функция, вам нужно читать комментарии (если они есть!) или, что еще хуже, копаться в коде! Это же ужас! Статический язык – это открытая книга! Типы данных явно указаны, и код становится самодокументируемым! Это огромное преимущество, особенно в командной работе и при поддержке кода через годы!

    Производительность? Забудьте! Динамические языки медленнее статических – это факт. Да, для простых скриптов это не критично. Но когда дело доходит до высоконагруженных приложений, разница становится огромной! Вы хотите, чтобы ваш сайт тормозил и падал под нагрузкой? Используйте динамический язык! Хотите скорости и надежности? Выбирайте статику!

    Инструменты разработки? IDE для статических языков – это космические корабли! Автодополнение, рефакторинг, статический анализ – все работает на порядок лучше, чем в динамических языках. Потому что IDE знает типы данных! Она может вам реально помочь, а не просто подсвечивать синтаксис!

    Я не говорю, что динамические языки – это зло. У них есть свои ниши. Для прототипирования, для небольших скриптов, для обучения – они могут быть полезны. Но для серьезных, долгосрочных проектов, для проектов, где важна надежность, масштабируемость и поддерживаемость – динамические языки – это тупик!

    Хватит уже цепляться за "легкость" и "быстроту" разработки на начальном этапе! Эта "быстрота" обернется годами мучений и отладки в будущем! Выбирайте статические языки! Выбирайте надежность, предсказуемость и спокойствие! Избавьтесь от головной боли, которую вам дарят динамические языки! Перестаньте писать на динамических! Пожалуйста! Ваш уставший и измученный разработчик.


    1. ednersky Автор
      31.01.2025 09:00

      Но, черт возьми, когда дело доходит до серьезных проектов, эта "магия" превращается в настоящий ад!

      в N-й раз это читаю и в N-й раз спрошу: в каких серьёзных проектах вы участвовали и можете ли привести пример серьёзного проекта?


      1. Dhwtj
        31.01.2025 09:00

        На проектах по 100-300.000 строк. Системы документооборота в каком-то смысле. Для министерств

        Один на c#, другой на PHP и все плюются от PHP проекта. По моим прикидкам усилий по сопровождению для сравнимых задач и инцидентов на нём нужно в 5 раз больше


        1. ednersky Автор
          31.01.2025 09:00

          были ли в проекте интеграционные тесты? и сколько из 100.000 строк было в тестах?


          1. Dhwtj
            31.01.2025 09:00

            Немного. В основном на интеграцию с внешними системами. Да и то в основном не код, а тестовые данные, ключи, инфраструктура.


            1. ednersky Автор
              31.01.2025 09:00

              ну вот вам и ответ


              1. Dhwtj
                31.01.2025 09:00

                Какая связь между количеством интеграционных тестов и (вероятно, вы про это) стабильностью приложения?


                1. ednersky Автор
                  31.01.2025 09:00

                  эм, а что такое стабильность?

                  в моей голове, это устойчивость к различным (в том числе неожиданным) действиям пользователя.

                  а так же устойчивость к изменениям, которые будет вносить новичок-программист

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

                  пришёл программист, исправил кусок кода, запустил тесты - два упало. Он полез разбираться и понял: зачем нужен вот этот кусок кода и вон тот. И из новичка постепенно стал превращаться в эксперта.

                  как-то так это и работает. А типы тут ни с какого бока не помогают, а только вредят - ибо умножают кодовую базу на два.


                  1. Dhwtj
                    31.01.2025 09:00

                    Покрыть всё тестами для полного регресс тестирования это умножить кодовую базу на два.


                    1. ednersky Автор
                      31.01.2025 09:00

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

                      а здесь кроме тестов человечество ничего не придумало.

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

                      кстати, в пассаже про мутабельность вселенной ИИ цитировал меня. В этом месте вопрос - кто автор текста, выдаваемого ИИ.


                  1. IUIUIUIUIUIUIUI
                    31.01.2025 09:00

                    так вот, нормальные интеграционные тесты помогают в обоих случаях

                    Бездоказательное утверждение.

                    смоделировали действия пользователя в тесте - поправили. тест сохранился на будущее.

                    Трата времени. Без тестов быстрее прокликали, и всё. Тем более, успехов в тесте воспроизвести всё богатство окружений пользователя.

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

                    как-то так это и работает

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

                    Тесты не-ну-жны и вредны.


                    1. ednersky Автор
                      31.01.2025 09:00

                      Бездоказательное утверждение.

                      интеграционный тест фиксирует внешнее поведение, а что внутри пользователю в 99% случаев неинтересно ибо в 99% случаев он и не имеет возможности ознакомиться с тем, что внутри.

                      Трата времени. Без тестов быстрее прокликали, и всё.

                      прокликали - это и есть тесты. просто выполняете их вручную.

                      Тесты не-ну-жны и вредны.

                      тесты решают реальные проблемы, типы решают проблемы надуманные. Доказательством тому - статистика мест, где пользователи чаще делают ошибки. Вон результаты опроса выше.


                      1. IUIUIUIUIUIUIUI
                        31.01.2025 09:00

                        интеграционный тест фиксирует внешнее поведение

                        1. В одном конкретном случае из миллионов.

                        2. На это надо потратить время, и ради чего?

                        3. Если фиксирует, то это ограничивает мою свободу дальнейшей разработки. Вы что, не настоящий программист, которому нужны костыли-подпорки, чтобы писать код?

                        прокликали - это и есть тесты. просто выполняете их вручную.

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

                        тесты решают реальные проблемы

                        Так какие проблемы они решают, кроме повышения зарплаты в потогонках через демонстрацию написанных строк кода, и прикрытия ЧСВ тимлидов, мастурбирующих на совершенно бессмсыленные метрики вроде code coverage?

                        Доказательством тому - статистика мест, где пользователи чаще делают ошибки.

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


    1. ednersky Автор
      31.01.2025 09:00

      Вот вам пример из жизни: Представьте себе функцию, которая должна принимать число и возвращать его квадрат. В динамическом языке вы можете случайно передать ей строку. И что произойдет?

      1. люди ошибаются всегда. вот какой язык ни возьми - ошибки будут

      2. далее, ошибки мы классифицируем: ошибки типов (о которых Вы пишете) vs прочие ошибки

      3. смотрим в статистику: прочие ошибки занимают большинство, а ошибки типов наиболее редки

      Вопрос: стоит ли из-за причины редко приводящей к проблемам сажать самого себя в клетку типовых нотаций, чтобы ещё чаще попадать в проблемы в и без того частотных случаях?


      1. Dhwtj
        31.01.2025 09:00

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

        Для понятности: программа на c# была написана 4мя людьми за год. В первые 5 лет её доработкой и сопровождением занимался один человек. Теперь там 0.3 ставки.

        Программа на PHP была написана 5(?) людьми за год. Прошло 10 лет. Сейчас её сопровождением занимаются 2 человека фуллтайм, бл@, не считая тестировщика и менеджмента. И это при почти полном отсутствии нового функционала


        1. ednersky Автор
          31.01.2025 09:00

          разработчик уходит, продукт превращается в легаси. И тут начинается ад.

          эта ситуация не зависит от языка, типов, чего угодно. только от разработчика

          • есть ли CI/CD на проекте?

          • есть ли тесты на проекте? если новый разраб до конца не понимающий что делает внесёт изменения и у него упадёт тест - это одна ситуация, а если теста как такового нет, индикатора "правильно ли я делаю" то будет ад

          и да, типы на роль этого индикатора не подходят, поскольку большинство ошибок, что делает любой программист - не ошибки типов (передача килограмм вместо квадратных метров), а ошибки логики (неучёт кеширования, неправильные математические операторы (> вместо >=) и так далее)


          1. Dhwtj
            31.01.2025 09:00

            Отсутствие типов это не столько передача килограмм вместо квадратных метров сколько передача невалидных данных. 31 мартабря, например.

            Да, вы может поставить валидатор данных в те места где данные insert/ update в базе. Но если этих мест под сотню, как в моём случае, то задумаешься о всегда валидных инвариантах, а их лучше делать на типах; хотя можно и без них, да, но часть гарантий теряется.


            1. vadimr
              31.01.2025 09:00

              Тут не всё так просто в реальной жизни. Как у того чувака, которому в роддоме записали дату рождения 31 ноября, и много лет никто не замечал.


    1. kalitkinvlad
      31.01.2025 09:00

      Удобно было бы для прототипирования, mvp и длительной поддержки чтобы в ЯП был настраиваемый компилятор: слабая типизация -> сильная -> строгая. А еще: ПП -> ООП -> ФП.


      1. Dhwtj
        31.01.2025 09:00

        MyPy может проверять по сильной и строгой типизации. Но пока плохо. И IDE подсказки сразу не выдает.

        И мне для прототипирования не понадобилось отсутствие типов ни разу ЧЯДНТ? Даже трудно представить, когда такое может быть. Пример можно?


        1. vadimr
          31.01.2025 09:00

          printf


          1. IUIUIUIUIUIUIUI
            31.01.2025 09:00

            А что с ним нетипизируемого? Даже хаскель может.


            1. vadimr
              31.01.2025 09:00

              Ясное дело, что спецификации формата – это затычки для статически типизируемых языков, и хотелось бы, чтобы всё работало без них.


              1. IUIUIUIUIUIUIUI
                31.01.2025 09:00

                Только при этом они есть даже в питоне. Просто спецификации формата — это, внезапно, спецификации формата, которые нужны, чтобы показать, условно, сколько знаков после запятой печатать, а не что-то там затыкать. Использование %d или %f в том же питоне — это просто дань традиции, чтобы программистам из других языков было проще и привычнее.

                Нет никаких причин, почему нельзя было бы писать просто % в хаскельном printf — типы аргументов всё равно известны статически, и как их печатать, тоже известно статически. Просто WTF-момент от простых процентов больше, чем экономия пары знаков.

                А написать типизированный принтф, терм которого после частичного применения к чему-нибудь вроде

                printf "Hello {}, your age is {}"

                имел бы тип Show a ⇒ Show b ⇒ a → b → String , даже проще, чем париться с полноценным разбором строки форматирования в компилтайме и последующим тайпчекингом аргументов.


                1. vadimr
                  31.01.2025 09:00

                  Не нужны вообще проценты, кроме очень специальных случаев. Наиболее часто используемая функция print() в питоне не типизирована, и это просто удобно.


                  1. IUIUIUIUIUIUIUI
                    31.01.2025 09:00

                    Ну так см. последний абзац.

                    Или Data.String.Interpolate.


  1. Dhwtj
    31.01.2025 09:00

    АД МУТИРУЮЩИХ МАССИВОВ: Когда ваш код превращается в минное поле!

    Вы думаете, что уже испытали боль динамической типизации? Позвольте мне рассказать вам о мутирующих нетипизированных массивах! Это как темная материя в вашей кодовой базе – вы знаете, что она есть, но понятия не имеете, что там внутри и как она себя поведет!

    Представьте себе проект, где в разных частях программы, словно злобные гномы, разработчики пишут данные в один и тот же массив. И, конечно же, никто не знает, что именно там должно быть! Сегодня там строки, завтра числа, послезавтра – объекты, а может быть, и вовсе null или undefined! Хаос! Беспорядок! Анахия!

    Вот вам ужасающий пример из практики:

    Допустим, у нас есть массив data. В начале программы он вроде бы предназначен для хранения имен пользователей. Но потом:

    • В функции processUserData() кто-то решил добавить туда возраст пользователя (числом, конечно же!). "Ну а что такого?" - подумал он. "Массив же динамический, вместит все!"

    • В модуле reportGenerator() другой разработчик, не разобравшись, решил использовать этот же массив для хранения статистики по пользователям (объекты с полями name, регион, активность). "Удобно же, все в одном месте!" - решил он.

    • А в каком-нибудь utilityFunctions.js вообще решили очистить этот массив в какой-то момент, "чтобы память не засорять". "Ну а что, если он больше не нужен?" - подумал этот "гений".

    И вот, вы, бедный разработчик, приходите в этот проект и вам нужно разобраться, что же, черт возьми, происходит с этим массивом data! Вы открываете код и видите:

    // Где-то в начале программы
    let data = [];
    
    // Функция 1: Обработка данных пользователя
    function processUserData(user) {
      data.push(user.name); // О, имена пользователей! Вроде понятно...
      data.push(user.age); // Стоп! А вот и возраст! Уже не только имена...
    }
    
    // Функция 2: Генерация отчета
    function reportGenerator() {
      data.push({ name: "Статистика", region: "Центр", активность: 150 }); // Объекты? Что за чертовщина?!
    }
    
    // Функция 3:  Утилита очистки (кто вообще додумался до этого?!)
    function clearData() {
      data = []; //  БАБАХ! Массив просто обнулили! Все данные исчезли!
    }
    
    // Где-то в конце программы
    function displayData() {
      for (let i = 0; i &lt; data.length; i++) {
        console.log(data[i].toUpperCase()); // Ой-ой-ой! А если там число или объект?!
      }
    }
    

    Что происходит в displayData()? Кошмар! Абсолютный кошмар! Мы пытаемся вызвать toUpperCase() на чем угодно! Если в массиве окажется число, объект или null, программа просто рухнет с ошибкой! И чтобы понять, почему она рухнула, вам придется прочитать ВЕСЬ КОД, где хоть как-то упоминается массив data! Вам нужно будет пройтись по всем функциям, которые его модифицируют, и попытаться угадать, что же там может оказаться в итоге!

    Это как игра в рулетку с гранатой! Вы никогда не знаете, что вытащите из этого массива! Это источник бесконечных ошибок, непредсказуемого поведения и боли в сердце разработчика!

    В статически типизированном языке такой ад просто невозможен! Вы бы объявили тип массива, например, Array<string>. И компилятор не позволил бы вам запихнуть туда ни число, ни объект! Он бы заорал на вас еще на этапе компиляции! Он бы спас вас от этого кошмара!

    Мутирующие нетипизированные массивы – это как черная дыра в вашем коде! Они поглощают время, нервы и здравый смысл! Они делают код нечитаемым, неподдерживаемым и крайне хрупким!

    Хватит! Хватит этой боли! Хватит писать код, который превращается в минное поле! Переходите на статические языки! Дайте себе шанс работать с предсказуемым и надежным кодом! Избавьтесь от ада мутирующих массивов! Ваше психическое здоровье скажет вам спасибо!

    Пожалуйста, ради всего святого, перестаньте писать на динамических языках (там, где это не оправдано)! Дайте нам всем жить спокойно!


  1. Dhwtj
    31.01.2025 09:00

    Чистые функции и статическая типизация: Честный контракт в мире хаоса! Крик облегчения разработчика! (И проклятия в адрес хаоситов!)

    Ах, чистые функции! Оазис ясности в этом болоте мутирующего состояния и динамического безумия! Если динамическая типизация – это анархия и хаос, то чистые функции и статическая типизация – это закон и порядок! Это честный контракт, заключенный между вами и вашим кодом!

    Вы устали гадать, что же делает функция, глядя на ее код? Вы замучились разбираться, какие побочные эффекты она может вызвать, как тайный агент, подрывая основы вашего приложения? Забудьте об этом кошмаре! С чистыми функциями и статической типизацией вы получаете прозрачность и предсказуемость, как никогда раньше!

    Что такое чистая функция? Это как священный Грааль в мире программирования! Это функция, которая:

    1. Всегда возвращает один и тот же результат для одних и тех же входных данных. Как часы! Никаких сюрпризов! Никакой магии! Только честный, детерминированный результат!

    2. Не имеет побочных эффектов. Она не меняет ничего вне своей области видимости! Она не мутирует глобальные переменные, не пишет в файлы, не отправляет запросы в сеть (в "чистом" смысле). Она чиста, как слеза младенца! Она делает только то, что заявлено в ее имени!

    А теперь добавьте к этому статическую типизацию! И вот тут начинается настоящая магия! Статическая типизация – это нотариально заверенный контракт для вашей функции! Вы явно указываете типы входных данных и тип возвращаемого значения! Это как паспорт для вашей функции! Все знают, кто она, что она принимает и что от нее ожидать!

    Посмотрите на это, это же поэзия!

    // TypeScript - статически типизированный язык, с чистыми функциями - просто песня!
    
    /**
     * Чистая функция, которая складывает два числа.
     * @param a - Первое число (обязательно число!)
     * @param b - Второе число (обязательно число!)
     * @returns Сумма двух чисел (всегда число!)
     */
    function add(a: number, b: number): number {
      return a + b;
    }
    

    Посмотрите на это великолепие! Из самого вида функции все понятно! Четко, ясно, без двусмысленностей! Вы видите:

    • function add(a: number, b: number): number - Это контракт! Функция add принимает два аргумента a и b, оба типа number, и возвращает значение типа number. Никаких "может быть строка", "может быть объект", "может быть null"! Только числа! И только число на выходе!

    • Комментарий: Дополнительно поясняет, что функция делает. Но даже без комментария, типы говорят сами за себя!

    Это честный контракт! Вы знаете, что если вы передадите в add два числа, вы гарантированно получите число в результате! И функция ничего не сломает в вашем приложении! Она просто сложит два числа и вернет результат! Просто, понятно, надежно!

    А что в динамическом мире? А там – темный лес! Там – царство хаоса! Там – вотчина проклятых хаоситов, которые, кажется, специально пишут код так, чтобы потом нормальные разработчики сходили с ума, пытаясь его исправить!

    // JavaScript - динамический язык, чистые функции - как редкие цветы в болоте
    
    /**
     * Функция, которая вроде как складывает два числа... или нет?
     * @param a - Что-то... наверное число?
     * @param b - И это тоже... наверное число?
     * @returns  Что-то... может быть число? А может и нет?
     */
    function add(a, b) {
      this.secret = null;
      throw "а вот фигу!";
      return a + b; // А что, если a или b - строка?  Что будет?  Никто не знает!
    }
    

    Смотрите на это убожество! Из вида функции ничего не понятно! Какие типы данных она принимает? Какой тип данных она возвращает? Гадание на кофейной гуще! "Наверное числа?" - робко предполагает комментарий. Но никто не гарантирует! JavaScript молчит, как рыба об лед! Он принимает все, что вы ему подсунете, и потом выстрелит вам в ногу в самый неподходящий момент!

    И вот я, бедный разработчик, сижу и отлаживаю код, написанный этими... этими... проклятыми хаоситами! Как я устал исправлять ошибки в вашем коде, господа динамические "волшебники"! Как я устал тратить часы на поиск банальных опечаток и несоответствий типов, которые статический компилятор выловил бы за секунды!

    Чистые функции и статическая типизация – это не просто "фичи". Это – уважение к себе и к другим разработчикам! Это – ответственность! Это – профессионализм! Это – способ писать код, который не будет превращаться в адскую кашу через полгода!


    1. ednersky Автор
      31.01.2025 09:00

      Что такое чистая функция? Это как священный Грааль в мире программирования!

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

      1. чистых функций (или количество кода, что можно выделить в чистые) - 1%

      2. остальное так или иначе связано с чтением/сохранением данных на диск, в базу, в сеть

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

      э... ну давайте, только непонятны два момента

      • кто реально будет зарабатывать те деньги, что уйдут на зарплаты этим сектантам?

      • что делать, если таких громкокричащих станет больше?

      ибо есть прецеденты:

      вот были в США/Европе громкокричащие ЛГБТ. Пошли у них на поводу, и их всё больше и больше.

      Теперь есть громкокричащие BLM и SJW.

      И всё бы ничего, но представители BLM, LGBT и SJW оказывают негативное влияние на общество в целом. Вот как адепты типов оказывают негативное влияние на мир программирования, так и представители РПЦ, BLM, LGBT и SJW (устанешь перечислять аббривеатуры) на мир в целом.

      Вроде бы ничего страшного, ну кричат и кричат. А потом смотришь: чтобы написать функцию о 5 строках теперь уже надо контракт на 25 строк описать.

      А ведь всего 10 лет назад было иначе!

      Чтобы отдать ребёнка в школу, нужно согласиться что ему православием голову будут промывать... А ведь всего 10 лет назад было иначе!

      и так далее


      1. Dhwtj
        31.01.2025 09:00

        чистых функций (или количество кода, что можно выделить в чистые) - 1%

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

        Императивная оболочка может занимать много кода. Но это не проблема. Требования к ней просты, она легко тренируется. Это то, что встречал.


        1. ednersky Автор
          31.01.2025 09:00

          вот у нас есть, например, крупный интернет-магазин.

          ну скажем Яндекс-маркет.

          да, конечно, если из всего проекта на миллион строк выделить чистые функции, то их соберётся где-то в пятьдесят тысяч строк. Дофига? Дофига!

          вот только остаток из 950 тыс строк никуда не денется.


          1. Dhwtj
            31.01.2025 09:00

            50.000 очень ответственных строк! И 50% дефектов по количеству и 70% по важности для бизнеса (по цене) у меня приходилось именно на эти 5-10% кода. И мне было очень интересно найти эти 5% кода чтобы его переписать. Потому что переписать 10% кода ресурсов уже не было.

            Не буду обобщать на все проекты, допускаю что бывает и по другому.


            1. ednersky Автор
              31.01.2025 09:00

              50.000 очень ответственных строк!

              да я не против. но эти строки - это всего 5% всех строк в проекте

              но вы предлагаете ЗАТРУДНИТЬ написание оставшихся 95% в угоду этих 5%

              И 50% дефектов по количеству и 70% по важности для бизнеса

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


              1. Dhwtj
                31.01.2025 09:00

                Ну, если вам затруднительно писать эти 95% в типах то их можно вынести в микросервисы на питоне например.


                1. ednersky Автор
                  31.01.2025 09:00

                  здесь есть и второй фактор. нам нужно выкопать 1000 кубов грунта.

                  мы пригнали экскаватор и выкопали всю 1000 одним ковшом. Ну а там где нужно было "тонко" - бригада с лопатами поправила после ковша. да вручную, но трудозатрат получилось: 1 человекодень экскаваторщика и 10 человекодней работяг с лопатами.

                  потом приходит чувак и заявляет: вместо этих 10 человекодней "тонкими" работами мог бы заниматься вот этот суперэкскаватор. Ему, правда, нужно пять человек в обслуживание и 1000 кубов он пять дней будет копать, но ведь зато универсально! Айда внедрять!

                  и начальство (в виде Google) говорит "айда внедрять!"

                  и вот мы копаем карьеры новыми суперэкскаваторами, способными размеры ям с точностью до сантиметра удерживать.

                  Ну да, медленнее это, ну да больше людей теперь требуется. Зато какой эффект!

                  Вот как-то так у нас и с типами


    1. ednersky Автор
      31.01.2025 09:00

      Смотрите на это убожество! Из вида функции ничего не понятно! Какие типы данных она принимает? Какой тип данных она возвращает?

      во-первых, всё понятно: функция судя по названию производит сложение

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

      в-третьих, видно, что автор функции обозначил ЧП вида "я её ещё не доделал", вставив выброс исключения в основной workflow. У вас два выхода: попросить автора доделать, либо самому доделать.

      Какой тип данных она возвращает?

      Фиксация на типах выглядит как психотравма.

      зачем Вам эти типы?


      1. Dhwtj
        31.01.2025 09:00

        видно, что при ЧП она выбросит исключение

        Это вам пришлось читать код.


        1. ednersky Автор
          31.01.2025 09:00

          открою страшную тайну: вам в любом случае придётся читать код.

          потому что будут функции и такого вида:

          func add(a int, b int) int {
            return a / b
          }

          Как видите, с описанием типов здесь полный порядок, но функция не только делает не то, что надо, она при некоторых значениях аргумента ещё и паникует!


          1. Dhwtj
            31.01.2025 09:00

            Такое из библиотек выгоняют ссаными тряпками

            Как минимум в описании должно быть указано такое, чтобы при использовании это прочитать в IDE

            // add(a, b)
            //
            // Выполняет целочисленное деление первого аргумента `a` на второй аргумент `b`.
            //
            // :param a: Делимое (целое число).
            // :param b: Делитель (целое число).
            // :return: Результат целочисленного деления `a` на `b` (целое число).
            //
            // :raises PanicError: Вызывает панику, если `b` равен 0 (деление на ноль).
            //
            // :note: Название функции "add" вводит в заблуждение, так как функция выполняет деление, а не сложение.
            //        Рекомендуется переименовать функцию в "divide" или "integerDivide" для большей ясности.
            func add(a int, b int) int {
              return a / b
            }


            1. ednersky Автор
              31.01.2025 09:00

              это же может быть просто ошибка

              пока функция делает, что нужно, внутрь неё и смотреть незачем


              1. Dhwtj
                31.01.2025 09:00

                Зависит от степени ответственности.

                Ну вот ещё случай из жизни: географически распределенная аналитическая система. Очень ярко выраженная пиковая нагрузка когда подают месячную и квартальную отчётность. И когда ошибка уже случилась то её исправлять просто нет времени. Даже логирование почти бесполезно. Решили методами защитного программирования: выделение бизнес логики в компактный и понятный код, для ненадёжного из-за сети ETL добавили новую систему повторов, основанную на строгой машине состояний, добавили параноидальную обработку io - даже от разрыва сети приложения с локальной БД.

                И теперь работает стабильно, уже больше года как без инцидентов.


          1. IUIUIUIUIUIUIUI
            31.01.2025 09:00

            В нормальном языке для начала было бы

            add : (a b : Int) → {auto nonZero : b ≠ 0} → Int

            потому что иначе тело бы не скомпилировалось, например. Опа, и у вас нет паник.

            Потом вы бы попытались доказать какие-нибудь свойства этой функции, вроде add a (add b c) = add (add a b) c, и у вас бы это не получилось, и вы бы подумали, что add делает какую-то ерунду (и правда, делает ерунду). Опа, и у вас нет вранья в именах.

            А в тестах без типов бы вы написали add (-4) 2 = -2 и пошли бы дальше писать микросервисы для кэширования, не заметив, что делаете ерунду.


            1. ednersky Автор
              31.01.2025 09:00

              Потом вы бы попытались доказать какие-нибудь свойства этой функции

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

              Нет, конечно, эти 99% функций могут быть разделены на чистые vs грязные, но здесь есть два момента:

              • размер кодовой базы от такого действия удвоится (а то и утроится) - что никому не нужно.

              • тестировать "грязные" всё равно придётся.

              Пат


              1. IUIUIUIUIUIUIUI
                31.01.2025 09:00

                Я не понимаю, как вы можете это всерьёз писать после того, как вы сами попросили меня реализовать выбранную вами (и по-вашему грязную) функцию в ФП, я это успешно сделал, выделив одну строку на грязь и дюжину строк на чистоту (такое-то удвоение ×2), и в итоге всё равно всё занимало меньше, чем у вас в вашем языке.

                размер кодовой базы от такого действия удвоится (а то и утроится) - что никому не нужно.

                А чё не удесятерится? Откуда здесь хотя бы даже удвоение?

                тестировать "грязные" всё равно придётся

                Зачем?

                Пат

                Мат. У меня. В адрес ваших способностей к восприятию текста, либо вашей благонамеренности в дискуссиях (возможно, вы просто шитпостите, и полное игнорирование эмпирических свидетельств с другой стороны является обманом, чтобы набрать классы).


                1. ednersky Автор
                  31.01.2025 09:00

                  прочее скипну ибо повтор, устал

                  > тестировать "грязные" всё равно придётся

                  Зачем?

                  затем, что этот код мы пишем? пишем.

                  прежде чем отдавать его клиентам убедиться нужно, что он работает? нужно


                  1. IUIUIUIUIUIUIUI
                    31.01.2025 09:00

                    прочее скипну ибо повтор, устал

                    Что вы устали? Игнорировать эмпирические данные? Так вы и в прошлый раз это скипали и не отвечали по существу. Я вам пример, как разделение на чистые и нечистые функции не увеличивает объём кода, вы продолжаете бегать с «в два, нет, в три, нет, в десять раз больше пять экранов текста!»

                    затем, что этот код мы пишем? пишем.

                    Это тупейший клей между рантайм-системой и вашей бизнес-логикой. Там нечего тестировать.

                    прежде чем отдавать его клиентам убедиться нужно, что он работает? нужно

                    Карго-культ и секта.


                    1. ednersky Автор
                      31.01.2025 09:00

                      Что вы устали?

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

                      Это тупейший клей между рантайм-системой и вашей бизнес-логикой. Там нечего тестировать.

                      этого кода в современном мире около 90%. вместо того чтобы тащить в мир типы, вы бы лучше придумали как эти 90% сократить хотя бы до 50.

                      Карго-культ и секта.

                      вот-вот! сектанты не хотят разговаривать о том, что нужно для бизнеса. Им всё бы какие-то неведомые теоремы доказывать, да ряд Фибоначчи программировать.

                      а меж тем в реальной жизни никому не нужны ни теоремы ни ряды Фибоначчи. И рекурсия тоже не нужна.


                      1. IUIUIUIUIUIUIUI
                        31.01.2025 09:00

                        отвечать на одинаковые вопросы

                        Как вы могли устать отвечать, если ни единого ответа на это от вас не было?

                        при том, что оппонент полностью игнорирует аргументы

                        Как можно игнорировать то, чего нет?

                        этого кода в современном мире около 90%. вместо того чтобы тащить в мир типы, вы бы лучше придумали как эти 90% сократить хотя бы до 50.

                        Я вам снова на примере показал, как это количество сократить до round $ 1 / (1 + 12) = 8%, а вы снова это игнорируете.

                        сектанты не хотят разговаривать о том, что нужно для бизнеса

                        Абсолютно верно. Бизнесу не нужны тесты и аджайл. Бизнесу нужен работающий код. Ваше слепое поклонение тестам совершенно необоснованно.


                      1. ednersky Автор
                        31.01.2025 09:00

                        Абсолютно верно. Бизнесу не нужны тесты и аджайл. Бизнесу нужен работающий код.

                        вот!

                        и никто не видел работающего, полезного ФП кода!

                        разговоры о теоретической возможности такового - сколько угодно

                        критиканство традиционных подходов - ещё больше

                        полезного выхлопа - ноль!


                      1. IUIUIUIUIUIUIUI
                        31.01.2025 09:00

                        и никто не видел работающего, полезного ФП кода!

                        Причём тут ФП? Мы уже тесты обсуждаем, а они совершенно не нужны. Нет ни единого проекта, в котором использовались бы тесты и который был бы полезен.


                      1. ednersky Автор
                        31.01.2025 09:00

                        Я уже приводил пару примеров софта, которым вы (как и миллионы других людей) точно пользовались. Этот софт с тестами. Какие-то части этого софта и что-то из этих тестов написано лично мной.

                        Теперь Ваша очередь.


                      1. IUIUIUIUIUIUIUI
                        31.01.2025 09:00

                        Пользователю важно, что там есть тесты? Нет. Менеджменту и бизнесу важно, что там есть тесты? Нет.

                        Тесты ничего не добавляют, только вынуждают раздувать код в восемь и шесть седьмых раз, чтобы добавить все нужные моки, интерфейсы, SOLID и DI. Вы знаете, что в Штатах сейчас вообще правительство DEI запретило? Это просто хотели запретить DI из-за феерического разбазаривания ресурсов на пять экранов кода на каждую функцию, но просто когда печатали текст указа, то случайно вместе с D нажали на кнопку над ней (и тесты это не поймали, обратите внимание — толку с них?).


  1. Dhwtj
    31.01.2025 09:00

    ТЕСТИРОВАНИЕ БЕССИЛЬНО! СТАТИКА – ГАРАНТИЯ! Хватит обманывать себя тестами в динамическом болоте!

    Да, да, я слышу вас, динамические адепты! "Но у нас есть ТЕСТЫ!" - кричите вы, размахивая своими жалкими юнит-тестами, как соломинкой, пытаясь спастись от наводнения ошибок! ТЕСТЫ? В ДИНАМИЧЕСКОМ КОДЕ? ХА! Это как пытаться остановить цунами чайной ложкой!

    Вы можете писать тесты до посинения! Вы можете покрыть кодом 100% строк! Вы можете запустить их миллион раз! И ВСЕ РАВНО ВАШ КОД ОСТАНЕТСЯ ПОТЕНЦИАЛЬНО ПОЛОН ОШИБОК, КОТОРЫЕ ВЫ ПРОСТО НЕ МОЖЕТЕ ПРЕДУСМОТРЕТЬ!

    Почему? ПОТОМУ ЧТО ТЕСТИРОВАНИЕ – ЭТО ПРОВЕРКА ЧАСТНЫХ СЛУЧАЕВ! А ДИНАМИЧЕСКАЯ ТИПИЗАЦИЯ – ЭТО БЕСКОНЕЧНОЕ МНОЖЕСТВО ВОЗМОЖНЫХ СЛУЧАЕВ!

    Вы можете протестировать функцию с числами, строками, булевыми значениями, массивами, объектами... НО ВЫ НИКОГДА НЕ ЗНАЕТЕ, ЧТО ЕЩЕ МОЖЕТ ВЫЛЕЗТИ ИЗ ЭТОЙ ДИНАМИЧЕСКОЙ БЕЗДНЫ! Кто знает, какой безумный тип данных кто-то случайно подсунет вашей функции через месяц, год, или пять лет? В динамическом языке НИЧТО НЕ ГАРАНТИРУЕТСЯ! НИЧТО НЕ ЗАЩИЩЕНО! ЭТО – АНАРХИЯ ТИПОВ!

    Тесты – это как свет фонарика в темном лесу ошибок. Вы освещаете небольшой участок, и вам кажется, что все в порядке. Но стоит вам сделать шаг в сторону, и вы тут же можете провалиться в яму, которую не осветил ваш жалкий фонарик-тест! Лес ошибок слишком велик, фонарик слишком слаб!

    А теперь представьте себе СТАТИЧЕСКУЮ ТИПИЗАЦИЮ! Это не фонарик, это – СОЛНЦЕ! Оно освещает ВЕСЬ ЛЕС ОШИБОК! Оно выжигает тьму динамического хаоса!

    Статическая типизация – это НЕ ТЕСТИРОВАНИЕ! Это – ГАРАНТИЯ! Когда вы объявляете тип переменной, тип аргумента функции, тип возвращаемого значения – КОМПИЛЯТОР ГАРАНТИРУЕТ, что эти типы будут соблюдены! Это не "надежда", это не "вероятность", это – ЖЕЛЕЗОБЕТОННАЯ ГАРАНТИЯ!

    Статическая типизация – это как ВРАТА КРЕПОСТИ, ЗАПЕРТЫЕ НА СЕМЬ ЗАМКОВ, перед целым классом ошибок! Ошибки несоответствия типов, ошибки опечаток в именах переменных, ошибки неправильного использования функций – ВСЕ ЭТИ ОШИБКИ ПРОСТО НЕ МОГУТ ПРОСОЧИТЬСЯ СКВОЗЬ СТАТИЧЕСКУЮ ТИПИЗАЦИЮ! ВРАТА ЗАКРЫТЫ! КРЕПОСТЬ НЕПРИСТУПНА!

    Тесты пытаются найти ошибки ПОСЛЕ ТОГО, КАК ВЫ ИХ УЖЕ СДЕЛАЛИ! Статическая типизация ПРЕДОТВРАЩАЕТ ЦЕЛЫЕ КЛАССЫ ОШИБОК ЕЩЕ ДО ТОГО, КАК ВЫ ИХ СОВЕРШИТЕ! Это – ПРОФИЛАКТИКА ПРОТИВ ЛЕЧЕНИЯ! РАЗУМ ПРОТИВ ХАОСА! ГАРАНТИЯ ПРОТИВ НАДЕЖДЫ!

    В динамическом языке вы пишете тесты, чтобы хоть как-то попытаться компенсировать отсутствие типизации! Это – жалкая попытка залатать дыры в прогнившей лодке! Вы тратите кучу времени и усилий на написание тестов, которые НИКОГДА НЕ СМОГУТ БЫТЬ ИСЧЕРПЫВАЮЩИМИ! И все равно живете в постоянном страхе, что какая-нибудь ошибка вылезет в продакшене и обрушит все ваши усилия!

    В статическом языке вы пишете тесты, чтобы проверить ЛОГИКУ вашего приложения, а не ТИПЫ ДАННЫХ! Типы данных – это ГАРАНТИЯ КОМПИЛЯТОРА! Вы можете сосредоточиться на СУТИ ПРОБЛЕМЫ, а не на БОРЬБЕ С ДИНАМИЧЕСКИМ ХАОСОМ!

    Хватит уже обманывать себя иллюзией надежности, которую дают несовершенные тесты в динамическом коде! Хватит тратить время на бесконечную и бессмысленную погоню за исчерпывающим тестированием! ПЕРЕХОДИТЕ НА СТАТИКУ! ПОЛУЧИТЕ ГАРАНТИЮ! ИЗБАВЬТЕСЬ ОТ СТРАХА! НАЧНИТЕ ПИСАТЬ НАДЕЖНЫЙ КОД, КОТОРЫЙ НЕ РУХНЕТ ОТ ЛЮБОЙ МЕЛОЧИ! ВЫБИРАЙТЕ СТАТИКУ, ВЫБИРАЙТЕ ГАРАНТИЮ, ВЫБИРАЙТЕ РАЗУМ! И ЗАБУДЬТЕ О БЕССИЛИИ ТЕСТОВ В ДИНАМИЧЕСКОМ АДУ!

    Чего-то сам читаю и ржу


    1. ednersky Автор
      31.01.2025 09:00

      напишите статью, я полайкаю и приду в комменты.


      1. Dhwtj
        31.01.2025 09:00

        Может, напишу.

        Сам не разделяю такие крайности. Но ваша статья это какой-то троллинг, который вы упорно защищаете на серьезных щах.

        Я ответил таким же троллингом. Но всё-таки с юмором.

        В моих проектах типизация очень полезна. А что в ваших проектах? Если вас мучают на микросервисных галерах, то может лучше пойти в стартап?


        1. ednersky Автор
          31.01.2025 09:00

          Но ваша статья это какой-то троллинг, который вы упорно защищаете на серьезных щах.

          1. статью я написал с тегом "пятничное"

          2. в каждой шутке доля шутки

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

            А статья - это уже усталый ответ. Реакция.


      1. vkni
        31.01.2025 09:00

  1. ptr128
    31.01.2025 09:00

    Статья - откровенная попытка затеять сразу несколько холливаров и похоронить в них истину. Ну похвалит каждый свой "золотой молоток". А толку? От этого ни один "золотой молоток" не перестанет быть антипаттерном.

    Я бы рекомендовал раздувающим здесь холивары задать себе простой вопрос: "Ведь, если звезды зажигают - значит - это кому-нибудь нужно?" (с) В. Маяковский.