LINUX.ORG.RU

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

 ,


1

4

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

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

вас не смущает в данной цитате, что речь в нехороших тонах идет о си, а не с++? а я говорю о с++.

А тебя не смущает, что С++ является почти полным надмножеством С (с некоторыми оговорками) и все недостатки С в полной мере относятся и к С++? Расскажи, как ты пишешь на С++ без сишной слабой типизации, без сишных char, int и т.д., без сишных неявных преобразований типов и т.д. Очень интересно послушать.

archie
()
Ответ на: комментарий от cobold

Очень помогает от тупых распространены ошибок типа

А это следствие убогости подобных язычков, где мысль давно остановилась на функции/методе с передачей аргумента + оопэ тупичок и дальше пойти не в состоянии. Какие-то более сложные абстракции - это вообще забей. Банальный dependency injection - это уже большой шаг в сторону от этого всего и там тебя под капотом ждёт всё то, что делают динамические язычки - доступ по названию поля/метода/класса, проверка его наличия, падения в рантайме и никакое иде тебе никогда не объяснит, где ты поставил аннотацию не там. И, к сожалению, это всё, что в принципе жабакококомунити может из себя выдавать. Спринг - это жирная коричневая точка на таких вот ст недоязычках и живой монумент тупиковости их идей.

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

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

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

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

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

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

это в питоновском проекте такие страсти? И как отсутствие типизации помогает тебе это разгребать?

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

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

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

Python не приходилось использовать в разработке (PHP, Perl, JavaScript).
Интересно конечно узнать о том, насколько статическая типизация эффективней динамической в Python.

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

отсутствие типизации

Кек, ну ты и адепт. Всё, что не ст - отсутствие типизации.

как

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

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

Внезапно, временем доступа. Можно вполне опозориться с хешманой слив жс'у.

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

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

ну ты щас repl описал, а не динамическую типизацию.

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

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

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

Писать на дт языках намного сложнее, чем на ст.

Писать на дт языках качественный код намного сложнее, чем на ст.

Ровно по тем же причинам, почему качественно писать на ассемблере сложнее, чем на ЯВУ. Нет машинного контроля за корректностью программы.

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

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

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

Так в любом ЯП система типов что-то неспособна выразить.

Если брать Haskell, там практически невозможно реализовать что-то вроде

(-> a b ... b c) (Listof a) (Listof b) ... b (Listof c)
#<procedure:map>

То есть функция, которая принимает функцию от N аргументов и N списков и возвращает список результатов применения этой функции к элементам списков. В Haskell придётся писать отдельно map, ,ap2, map3, … (которые называбтся zipWith2, zipWith3, …).

Если брать даже Typed Racket, на котором этот самый обобщённый map типизируется, то даже в нём проблематично типизировать, например, продолжения.

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

ты там фетчишь что-то (жсон, как понимаю) из сети и гуляешь в репле по полям в начале разработки, или когда все полетело к чертям и надо разбираться «чево каво»?

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

Да поэтому самый популярный сайт для погромистов stackoverflow называется, а не traceback most recent call last

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

Здесь нет имплицитного вызова. Здесь

fun(&b) = fun(b.deref()) 

Выше указано, что deref всегда возвращает &A. fun хочет именно &A. Всё сходится.

Как я писал выше, глядя на

fn fun(a: &A) -> () { ... }
...
fun(&b)

достоверно можно утверждать, что &b имеет тип &A. Для C++ это не так. Тип может быть любым, для которого компилятор найдёт преобразование.

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

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

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

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

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

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

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

fun(b) = fun(b.operator_A())

Тем, что b не может быть b.operator_A(). Более того, в C++ может быть

f(b); // здесь он b.operator_A()
g(b); // здесь он b.operator_С()

Это и есть нестрогая типизация. Такая же в 1С, например. СокрЛП(А) работает для любого А, который можно привести к строковому типу.

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

И какая разница тогда? В ст я не могу делать key[value] для объекта, а в дт могу в любом случае. В ст мне надо думать, когда там юзать мапу, а когда нет, а в дт - не надо, когда придут данные говна, тогда и заюзается. Прошу заметить, что срач уже перетёк в разряд управление кучей руками vs аллокатор.

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

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

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

Бессмысленнее ts'а вообще ничего не видел. Такое говно надо постараться еще сделать.

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

Ок, ты говоришь, «не всем надо обходить поля объекта»?

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

Вот. Типичное решение для ст'ников - пили обёртку. А потом выходит так, что код на жс ест меньше по памяти и работает быстрее, кек.

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

Так было же. Очень быстро перешло в срач, что считать компилируемым.

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

Немного не по теме треда.

Число и дата дробилки неплохо помогают понять «вес» использования каждого оператора и управляющих операторов.

Пост о том, что бывают «big алгоритмы» и «ширпортреб».
И они весьма разнятся.

Python - для «ширпортреба».

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

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

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

P. S. Никто не мешает в ст добавить тип ИзменяемыйОбъект с методами «добавить поле» и «удалить поле». В 1С есть тип «Структура» именно с такой семантикой. И тип «ТаблицаЗначений», у которой поля строки определяются списком колонок этой таблицы.

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