LINUX.ORG.RU

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

 ,


1

4

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

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

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

Твой вой просто жалко выглядит

Жалко было смотреть на потуги, например, Егора Бугаенко, когда он в рамках жабки пытался сделать что-то там для себя.

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

О, этот метод кажись работает)

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

А на динамическом языке:

  • Можно сразу спроектировать правильную иерархию.
  • Можно вообще не проектировать иерархию.

?

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

А на динамическом языке:

  • Не требуется делать рефакторинг кода?
  • Рефакторинг кода делать проще?
  • Не бывает новых требований?
wandrien ★★
()
Ответ на: комментарий от alex1101

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

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

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

Какие конкретно возможности проектирования?

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

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

Ну де факто это сокращенная форма записи шаблона.

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

А на динамическом языке:

  1. Принято проще относиться к вещам, а не делать башню из слоновой кости.
  2. Быстрее и проще вносить изменения.

А на динамическом языке:

см. выше. Конечно, есть проблемы, но в целом хрупкость меньше.

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

Но это не отказ от типов. Это как раз мощь вывода типов.

Это не вывод. У compose нельзя написать тип.

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

Говорит о чем-нибудь этот список? Судя по твоим комментам - ни о чем не говорит.

Сам спросил, сам ответил, молодец. А со мной поспорить слабо?

Я возьму на себя смелость

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

В то время как в Жаве классы - это классы, и они обеспечивают инкапсуляцию,

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

питоне классы - это проходной двор

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

В динамических ЯП приходится заниматься тем же самым, но без какой-либо поддержки со стороны языка. Единственным инструментом, который он предоставляет, является «Господу нашему помолимся».

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

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

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

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

Пока в python и php тащат типы, в C++ от них фактически отказываются.

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

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

А какие идеи оказались состоятельными?

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

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

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

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

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

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

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

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

«Без вызова нет чувства преодоления», вот это всё.

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

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

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

Давай. Достанем и сравним. Я этого и пытаюсь добиться в этой теме уже который раз.

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

Аминь.

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

полиморфизма, наследования и инкапсуляции

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

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

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

Дааа. Скатился в агрументы к авторитетам. Жалкое зрелище.

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

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

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

Ну то, что ты не можешь «экспериментировать» на ст. ЯП, потому что в голове бардак, я уже понял.

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

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

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

Дааа. Скатился в агрументы к авторитетам. Жалкое зрелище.

Инигавари.

«А еще он книжки читал!»

Интеллигентишка сраный.

Вот рассказывать про жопу - это по не жалкое зрелище, это современно!

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

Вот это тоже компилируется:

int main() {
    auto x = compose(2, 3);
}

И только при вызове x() происходит реальная проверка типов.

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

формальное доказательство кода во все поля

не не не, это даже не про формальное доказательство, не о том, стоит ли делать проверки, а это о том когда их делать.

ты делаешь проверки, он, она, и даже они - все делают проверки!

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

  • извратиться, и вернуть что-нибудь особенное типа NaN
  • кинуть исключение
  • результат обернуть во что-нибудь типа Optional (или Maybe)

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

бедааа. и как дальше жыть?

запилить контракт на делитель! тадаааммм!

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

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

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

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

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

со специализированным ЯП было бы еще круче и веселее, но это немножечко утопия, так что на этом, пожалуй, мы и остановимся.

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

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

О боже мой, увидел какое-то говно, теперь всё, ужос. Сходи с психологу, там, я не знаю.

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

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

Почему нельзя то? Впечатление, что вам религия запрещает. Какой-то гуру ляпнул про «предпочитайте композицию», теперь кодерки с этим носятся как дурни со ступой. Так вот, «предпочитайте» не означает, что наследование харам. Просто перед тем, как наследовать, стоит немного подумать. Только и всего.

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

Вместо ответов по существу

Ох, лол, а у тебя были вопросы по существу?

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

Во-во. Наследование не всегда к месту, хотя бывает проще унаследоваться не думая об архитектуре кода.

Но борцы с ООП эти увидели слово «в поддержку» своей религии и понеслось.

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

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

т.е. проектировать в процессе:

  • невозможно
  • сложно
  • долго и муторно
  • свой вариант

?

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

это статистика вашего участия в проектах на яве

  • больше десяти
  • больше пяти
  • больше одного
  • одного

?

Для справки, совершенно обычные типы - не из букваря с картинками по ООП «кошечка и рыбка это наследники животного» - выглядят как-то так:

public class Area extends Object implements Shape, Cloneable {...}

public final class LocalDateTime extends Object implements Temporal, TemporalAdjuster, ChronoLocalDateTime<LocalDate>, Serializable {...}

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {...}

ехала композиция через интерфейсы, а не «башня из классов».

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

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

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

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

Да, интересно. Без y(); компилируется:

auto compose(auto f, auto g) { return [=](auto x) { return f(g(x)); }; }

int main() {
    auto x = compose(2, 3);
    auto y = x;
    y();
    return 0;
}
wandrien ★★
()
Ответ на: комментарий от arkhnchul

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

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

т.е. проектировать в процессе:

Дорого. Долго и дорого.

это статистика вашего участия в проектах на яве

10 лет работы в IT. Можем ещё зарплатой померяться.

ехала композиция через интерфейсы, а не «башня из классов».

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

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

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

Вы показали «проблему», которая возникает в статическом ЯП.

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

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

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

Ну да. Вот только в реальности это выльется в

Not0 x = 1; // 0 нельзя

int z;

cin >> z;

float y = float(z) / 3 - 2;

if (y != 0) x = y; // проверка для ублажения компилятора

// y = y + 1
float y1 = y + 1
if (y != 0) y = 1;

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

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

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

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

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

float y = float(z) / 3 - 2;

Читать как

float y = 0.2 + float(z) / 3 - 2;

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

ты пессимист )

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

«перед построением» а не «всегда».

компилятор конечно же знает момент «before function call» и может выполнить все необходимые проверки.

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

Компилятор проверяет, что может доказать, что присваиваемое значение не 0. Если не может, значит ошибка.

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

Это какой-то воображаемый компилятор, который имеет встроенный тип Not0.

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

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

Какие конкретно возможности проектирования?

На том же жс'е можно выразить твоё жабаооп с наследованием иерархией классов и всем, что ты там так любишь. Причем, не только выразить но и расширить/изменить саму концепцию.

Эмоциональные оценки не интересно обсуждать

Ну так перестань вести себя как истеричка, кто тебе доктор?

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

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

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

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

Что именно препятствует выстраиванию полностью верифицируемой на этапе статического анализа системы типов

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

и что с этим делать

Переехать во вселенную попроще %)

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

На том же жс’е можно выразить твоё жабаооп с наследованием иерархией классов и всем, что ты там так любишь. Причем, не только выразить но и расширить/изменить саму концепцию.

И зачем нужно «расширять концепцию»? Из любви к искусству? Это поможет проектировать программы? Чтобы что?

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

Выразить можно, а типы проверить нельзя.

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

Шутка

Так она рядом - 1С.
В ней ни статической, ни динамической типизации нет!

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

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

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

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

(define-type Not0 (U Positive-Exact-Rational Negative-Exact-Rational))

; безопасное деление
(: div (-> Exact-Rational Not0 Exact-Rational))
(define (div a b) (/ a b))

Вот про a - b:

(: foo (-> Not0 Not0 Not0))
(define (foo a b) (- a b))

Type Checker: type mismatch
  expected: Not0
  given: Exact-Rational in: (- a b)

А такое компилируется:

(: foo (-> Not0 Not0 Not0))
(define (foo a b)
  (define t (- a b))
  (if (= t 0) 1 t))
monk ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)