LINUX.ORG.RU

Зачем нужна статическая типизация?, или Вы всё врете!

 ,


1

4

В теме "Питонячьи радости " на последних страницах между мной и @rtxtxtrx внезапно разгорелся спор, из которого я понял, что есть еще люди, которые не считают динамическую типизацию (в том виде, в котором она представлена в Питоне, а именно строгая динамическая типизация) серьезным недостатком при работе с большим объемом кода, особенно при рефакторинге. Вообще изначально разговор завязался вокруг назначения type hints введенных в Питон 3: я утверждал, что они нужны для создания семантических связей в коде, которые будут препятствовать внесению деструктивных изменений в код в результате опечатки или иной ошибки кодера (изменил код, в результате которого какое-либо выражение получило некорректное значение, которое тем не менее обладает схожим с корректным значением типовым контрактом, поэтому при запуске код не «упадет» сразу, указав на проблему); оппонент заявил, что они нужны для (само)документации и не более того.
Но потом выяснилось, что и царь-то ненастоящий (читай, статическая типизация). Не нужна она, просто именуй сущности понятно и уповай на строгую типизацию. А если типизация не строгая, то сами виноваты, у нас в Питоне всё ОК.
Поскольку тема большая и вкусная, я предлагаю всем обсудить этот очень важный вопрос в меру скромных сил и познаний каждого желающего. Обсуждение вторичных вопросов, как-то «статическая типизация нужна для генерации эффективного кода», «при динамической типизации тип только один, object» etc. не предусмотрено — спорим только о том, дает ли статическая типизация выигрыш, если надо перекраивать несметные тыщи kloc. Если есть вообще о чем спорить 😅.

★★★★★
Ответ на: комментарий от monk

/me грустно пишет struct’ы для Go, а хочется как-то так:

kubectl get secret some-config -o json | jq -r '."data"."config.yaml"'|base64 -d

(в большой джейсонине все поля кроме нужного проигнорированы).

ugoday ★★★★★
()
Ответ на: комментарий от alysnix

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

Что, даже не скомпилируется?

ugoday ★★★★★
()

ИМХО логические ошибки, много «каверзней».
Бывает код выглядит как «правильный», а при тщательном анализе
выявляются немало не только логических ошибок, но и кривоватость алгоритма в целом.

Шутка

Используем try и все ошибки нам не страшны.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от alysnix

Пожалуй, в этом суть.

Скучно выписывать классы и сигнатуры методов и продумывать иерархии.

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

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

wandrien ★★
()
Ответ на: комментарий от Forum0888

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

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

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

wandrien ★★
()
Ответ на: комментарий от wandrien

Шутка

В 1С можно компилятору можно подсунуть хоть корень квадратный из объекта и он ругаться не будет.
Просто удивительно, но в 1С при этом несложно писать вполне корректный код, а ошибки run-time быстро исправляются.

Или к примеру, обращение через точку типа:

 Дуракам  = "";
 VpДураки = "";

 VpДураки = Дуракам.Закон.Не.Писан;

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

А Вам всем видите-ли Python не такой.
Радуйтесь!

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от Forum0888

Или к примеру, обращение через точку типа

К примеру, в 1С и Python этот код будет не работать одинаково. Узбагойтесь, Владимир.

anonymous
()
Ответ на: комментарий от ugoday

Профдеформация, как и было сказано. Подсказка: «IDE не дополняет дополнения» — это не проблема реального мира.

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

Вот пример из собственной практики. Есть довольно старый проект, который переписывали пару лет назад с 2.7, в процессе переписывания выяснилась удивительная вещь. Функция выглядела примерно так:

def create_key(metrics):
   """
      :type metrics: tuple(str, str, str) 
   """
   return "".join(get_metric_key(m) for m in metrics)

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

давай, скажи мне, что в твоём чудесном коде такое невозможно и «IDE не дополняет дополнения»

FishHook
()
Ответ на: комментарий от arkhnchul

Всё, что ложится на его систему типов пишется просто прекрасно: всякого рода преобразование текстов, списков, формул, вычисления…

С учётом типа Dynamic, там можно и динамическую типизацию использовать. Но когда хочется выразить то, что легко выражается в Typed Racket, а система типизации заставляет это делать через какие-то вспомогательные структуры, грустно.

monk ★★★★★
()
Ответ на: комментарий от FishHook

Да при чем здесь ИДЕ?

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

ugoday ★★★★★
()

Я кстати так и не понял нахрена нужны «type hints», все равно в рантайме они не проверяются. Похоже на еще один вариант комментариев.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Это когда в чужой огород да со своим уставом.

sambo ★★
()
Ответ на: комментарий от sambo

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

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

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

sambo ★★
()
Ответ на: комментарий от wandrien

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

sambo ★★
()
Ответ на: комментарий от wandrien

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от rtxtxtrx

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

rumgot ★★★★★
()
Ответ на: комментарий от rtxtxtrx

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

rumgot ★★★★★
()
Ответ на: комментарий от rumgot

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

В Typescript, например, бывают совершенно издевательскіе ошибки node_modules/path/to/type != node_modules/another/path/to/this/type. И вместо решения реальной проблемы приходится плясать вокруг компилятора. Особенно доводит, когда компилятор ты ублажил, но программа всё равно валится, потому что внезапно в одном из аккаунтов ты упёрся в лимиты AWS.

В Хасскелле (когда-то я делал подход к этому снаряду), жутко не понравилось, что программа должна быть корректно типизирована вся целиком, даже когда я этого не хочу. В процессе разработки я сам ещё не знаю как должен выглядеть результат, поэтому мне нужно делать много маленьких экспериментов. Я хочу из всей программы изменить пару функций и посмотреть как они себя поведут на определённых данных. Хрен тебе, золотая рыбка, переписывай половину функций, иначе не скомпилирую! Соответственно цикл идея→проверка→вывод замедляется и результат в целом становится хуже.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

нужно делать много маленьких экспериментов

Лишь Истинный Светоч Поможет.

Такая же проблема была с гошечкой, без репла как без рук.

Nervous ★★★★★
()
Ответ на: комментарий от ugoday

Выглядит так, что на Хаскеле надо было учиться по-другому разрабатывать программы. Я не утверждаю, что это будет так же быстро, как с REPL driving development 😊. Сильная статика делает код сильно связанным, что плюс, когда мы не можем обрушить его целиком изменениями в одном месте программы — потому что придётся не в одном месте это делать, чтоб статика это позволила сделать, но если мы хотим намеренно временно ввести систему в нестабильное положение, получая от этого определённую выгоду, мы не можем этого сделать.

Этот вывод, по крайней мере, полезен. Хотелось бы еще штангистов послушать по этому вопросу, желательно КМС как минимум.

Virtuos86 ★★★★★
() автор топика
Ответ на: комментарий от Virtuos86

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

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Аналогия хорошая, но таких людей

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

практически не бывает. Как и штангистов 🙂.

Virtuos86 ★★★★★
() автор топика
Ответ на: комментарий от Virtuos86

В Хаскеле тоже есть REPL: GHCi называется.

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

Да, есть небольшая дополнительная работа, если меняешь синтаксис типа. Например, передавал просто String и было

f uuid = ... uuid ...

Стал передавать newtype стало

f (UUID uuid) = ... uuid ...

Стал передавать data с 16 байтами

f buuid =
  let uuid = show buuid in ... uuid ...

Дальше от внутреннего устройства типа уже ничего не меняется.

И типы надо именовать, тогда сигнатура f будет вообще неизменной:

f :: UUID -> ...

В первом случае с String должно быть

type UUID = String
monk ★★★★★
()
Ответ на: комментарий от ugoday

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

А что поменять то хотел? Тип параметров? Возвращаемый?

Соответственно цикл идея→проверка→вывод замедляется и результат в целом становится хуже.

Т.е. этот довод в пользу того, что на языках с ДТ только MVP писать и идеи проверять?

rumgot ★★★★★
()
Ответ на: комментарий от ugoday

В Typescript, например, бывают совершенно издевательскіе ошибки

Пока TS не имеет собственного интерпретатора - это обвес для js. Вот когда будет, тогда может быть будет иначе.

rumgot ★★★★★
()
Ответ на: комментарий от anonymous

Узбагойтесь, Владимир.

Этот код ни в одном ЯП нормально работать не будет, но 1С такой синтаксис считает корректным.

«Узбагойся» аноним и не злобствуй.

Шутка

За это мы 1С любим, ценим и в обиду не дадим.
Для меня всё же «загадка», почему в 1С non problem с компилятором.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 1)
Ответ на: комментарий от monk

В Хаскеле тоже есть REPL: GHCi называется.

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

И типы надо именовать, тогда сигнатура f будет вообще неизменной:

f :: UUID -> ...

В первом случае с String должно быть

type UUID = String

Это «алиасы», насколько я понимаю. Есть такое, удобная штука.

Virtuos86 ★★★★★
() автор топика
Последнее исправление: Virtuos86 (всего исправлений: 1)

Спасибо Вам за этот тред.

Ещё много чего полезного можно сказать по теме треда.
Всё ещё впереди!

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от Virtuos86

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

По нормальной схеме REPL должен использоваться в связке с IDE. leksah и Emacs умеют.

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

monk ★★★★★
()
Ответ на: комментарий от monk

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

f x y z = ...

Потом в REPL пишешь:

:t f

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

monk ★★★★★
()
Ответ на: комментарий от monk

leksah

Лет -ть назад устанавливал — интерфейс разъезжался за края экрана, снес, очень понравилось. Судьба ☺️.

Virtuos86 ★★★★★
() автор топика
Ответ на: комментарий от monk

Помню, мне запомнился Hackage (если не путаю название сервиса) своей идеей: забил нужную сигнатуру, тебе выдает библиотечную функцию, которая делает, что тебе нужно.

Virtuos86 ★★★★★
() автор топика
Ответ на: комментарий от Forum0888

но 1С такой синтаксис считает корректным

Как и Python (нужно только убрать точки с запятой). Что ты пытаешься этим сказать?

anonymous
()
Ответ на: комментарий от Virtuos86

однострочник проверить какой, не более того

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

anonymous
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)