LINUX.ORG.RU

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

 ,


1

4

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

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

Так был уже пост об этом.

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

Это обобщенный код на C++ и в добавок алгоритм помещает результат в десятки разных структур (без использования class, ...).
В форуме много говорят о Лисп, ... какое в этих ЯП крутая работа с объектами.
Да ведь на Си и C++ можно много проще все эти «лунные» алгоритмы реализовать (без всяких class, template, struct, ...).

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

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

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

tuple[str, str, str]) -> str

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

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

Дружище, 1C предоставляет десятки отличных объектов и обобщённые алгоритмы в ней это типичный код, которым никого не удивишь.
К сожалению 1С пригодна лишь для задач а-ля учётных и некой ниши информационных систем.
Ныне правда фирма 1С поняла, что это «не очень» и работает над устранением этого недостатка.

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

Ну баш тоже ни для чего не пригоден кроме вызова других бинарников и какой-то простой логики. А 1С - это даже не полноценный язык, а всего-лишь DSL как какой-нибудь SQL.

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

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

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

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

Не скажу, что 1С-ики глупые, но вот расскажу одну быль.
Умнейший парень разработал ВК, которая позволяла в 1С использовать .net framework, так 1С-ники годами его «травили».

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

пытаются идти крестовым походом на типизацию

Три раза прочитал, прежде чем понял, что речь не про плюсы.

Два раза прочитал, прежде чем понял, в чём каламбур.

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

Вот, тут я лучше промолчу, давно хаскелл не трогал.

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

А «ТаблицаЗначений», «Структура», ... и десятки иных объектов почему не упомянули?
Что касаемо «Справочник», то в любой СУБД таблица это а-ля «Справочник».

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

Это фича языка, а не «что-то другое».

Ноуп, фактически в яву добавили ещё один язык, в результате можно в одном файле на двух языках писать (как html+php в древнем вебе).

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

только ни в PHP, ни в JS, ни в C#, ни в Python, ни в Go, ни в C++ таких встроенных типов данных нет, а я перечислил все на чем говнокодил

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

В секеле тоже есть, но это не делает его чем-то кроме DSL

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

Кстати, не сложно расширить функциональность 1С.

Можно вообще не создавать никаких объектов типа «Справочник», ..., а напрямую работать с какой-либо СУБД.
Возможностей - ОКЕАН!

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

А на секеле можно полностью всю бизнес-логику реализовать для простенького API и даже http-запросы отправлять с помощью расширений

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

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

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

Не обязательно бизнес логику в TSQL модули какой-либо СУБД помещать.
1С сама по себе СУПЕР TSQL (по функционалу).
Объект «Запрос» как раз и есть СУПЕР TSQL.

1С хороша, но для многих она стала (к сожалению) «болотом» (если кто понимает о чём речь).

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

Алгоритмы можно реализовывать и на Scratch, а потом появляются адепты NoCode

rtxtxtrx ★★
()
Ответ на: комментарий от ugoday
❯ python
Python 3.11.5 (main, Sep  2 2023, 14:16:33) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def foo(s: str):
...     ...
... 
>>> foo.__annotations__
{'s': <class 'str'>}
rtxtxtrx ★★
()
Ответ на: комментарий от ugoday

Вы можете вернуть из функции аннотацию, сделать цикл по массивам из аннотаций и т.п.?

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

monk ★★★★★
()
Ответ на: комментарий от ugoday
ClassWithAnnotations.class.getDeclaredField("classMember").getDeclaredAnnotations()
monk ★★★★★
()
Ответ на: комментарий от ugoday

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

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

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

Я даже в питон добавил статическое гомо-петушение:

import inspect
from typing import Any, Callable
from functools import wraps

def check_typing(f: Callable) -> Callable:
  @wraps(f)
  def wrap(*args: Any, **kwargs: Any):
    ba = inspect.signature(f).bind(*args, **kwargs)
    ba.apply_defaults()
    for key, value in ba.arguments.items():
      if not isinstance(value, f.__annotations__[key]):
        raise TypeError(key)
    return f(*args, **kwargs)
  return wrap

@check_typing
def add(a: int, b: int) -> int:
  return a + b
  
add(1, 3.14)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in wrap
TypeError: b
rtxtxtrx ★★
()
Ответ на: комментарий от monk

Удалил контент поста.

«Пока ещё не поздно мне сделать остановку, нажму на тормоза».

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

Оно как пример ненужного. Все-таки в тру-компилируемых языках все типы на этапе компиляции определяются и все потом не изменяются, а это динамика, тут программа «на лету сама себя изменяет». Оно слишком по-разному работает + сразу становится понятно почему в стандартной либе хотя бы декоратора для проверки типов нет: непонятно считать ли валидным None, float, bool, если в сигнатуре int, нужно ли приводить к целому, если да, то как? В PHP и Python есть тайп хинты теперь и это хорошо, вот бы их еще в JS завезли чтобы ублюдский TypeScript стал ненужным. Его использование кстати тупо и сводится к указанию типов

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

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

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

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

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

Вжух, и статическая типизация превратилась из серебряной пули

А это в каком лоре?

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

Ясно. Логику понял. В C/C++ пошли по пути разделения языка программирования, макроязыка, метаязыка, языка для написания компиляторов, языка для сценариев компиляции, языка для скриптов. У каждого свой синтаксис.

Можно всю лестницу от C до sh считать частью одной программной среды.

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

непонятно считать ли валидным None, float, bool, если в сигнатуре int

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

arkhnchul ★★★
()

Я еще вброс сделаю в питоне на данный момент вообще невозможно проверять типы в рантайме. mypy и pyright проверяют типы только до запуска кода, пробегаются так по ast и формально смотрят. Они не выполняют программу, а значит от падения в рантайме не избавят, если там все-таки носорог с бульдогом случатся (от слова случка. я, правда, не представляю как это может произойти, но пути дебилов неисповедимы). Тот пример, что я набросал, так можно проверить только классы, их методы и функции, но такое останется без проверки:

# Сюда мы ничего добавить не смогем никаких декораторов
result: UserList = govnoapi.users.get(q="Вася Пупкин")

Решением будет только пойти по пути TypeScript и компилировать ТупизированныйПитон в Питон для натуралов, но даже мелкософт с его возможностями не осилил сделать полноценную проверку. А посему акромя использования pydantic решений на сегодняшний день нет

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

Сюда мы ничего добавить не смогем никаких декораторов

но смогем напихать ассертов за ще… да просто через строку писать assert isinstance(govno, PetuhGovno) - вот тогда мы сможем MAKE PYTHON STATIC AGAIN (хотя он таким никогда не был). Есть же Nim почему бы его не использовать

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

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

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

rtxtxtrx ★★
()

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

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

#include <stdio.h>
int main (void)
{
 int a = 200;
 printf ("A = %d \n",a);
  {
    float a = -3.7;
    printf ("A = %f\n",a);
  }
 printf ("A = %d \n",a);
 return 0;
}

P.S. Поскольку я не прогер на Си, то при составлении сего примера копипастой я отстрелил себе the egg: сначала не поменял во втором printf %d на %f.

P.P.S. Вот такой код так же компилиться без ошибок:

#include <stdio.h>
int main (void)
{
 int a = 200;
 printf ("A = %d \n",a);
  {
    float a = -3.7;
    printf ("A = %f\n",a);
  }
 printf ("A = %f \n",a); 
 return 0;
}

Вот только если первый вариант правильно выдаёт

A = 200 
A = -3.700000
A = 200 

то второй выдаёт:

A = 200 
A = -3.700000
A = -3.700000

И напоследок любителям Си поразмышлять над приколом:

#include <stdio.h>
int main (void)
{
 int a=200;
 printf ("A = %d \n",a);
  {
    float a=-3.7;
    printf ("A = %f\n",a);
  }
 printf ("A = %d \n",a); 
 printf ("A = %f \n",a);
 float c = 3.7,q;
 q = c + a;
 printf ("Q = %f \n",q); 
 return 0;
}

Вот эта кривулина выдаёт прэлестный результат:

A = 200 
A = -3.700000
A = 200 
A = -3.700000 
Q = 203.699997 
mister_VA ★★
()
Ответ на: комментарий от mister_VA

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

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

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

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

Области видимости тут ни при чём

#include <stdio.h>
int main(void) {
  printf("A = %f\n", -3.7);
  printf("A = %f\n", 123);
  return 0;
}

А против закрывания переменных надо везде ставить -Wshadow -Werror

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

Там и не с переменными то же самое будет. Хотя я в начале подумал что -3.7 и 200 просто одинаково представлены.

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

я таки больше скажу

#include <stdio.h>

int main(){
    int a = 200;
    printf ("Ai = %d\n",a);
    printf ("Af = %f\n",a);
    float b = -3.7;
    printf ("Bi = %d\n",b);
    printf ("Bf = %f\n",b);
    printf ("Ai = %d\n",a);
    printf ("Af = %f\n",a);
    return 0;
}
Ai = 200
Af = 0.000000
Bi = -1438973280 (тут рандомный мусор насамделе)
Bf = -3.700000
Ai = 200
Af = -3.700000
arkhnchul ★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)