LINUX.ORG.RU

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

 ,


1

4

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

★★★★★

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

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

А еще делать такие конструкторы explicit считается best practice.

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

Это все еще строгая типизация.

Строгая типизация — когда при вызове f(x) ты можешь точно указать тип x. Как в Haskell или в питоне с декларациями.

В Си++ тип x может быть произвольный класс, реализовавший конструктор. Для арифметики в стиле JavaScript в C++ достаточно добавить конструктор std::string(double x).

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

Гм., у меня создание иерархического дерева на основании данных
объектов и метаданных глобального модуля из конфигурации 1С 7.7 (300MB) выполняется меньше секунды.

Проблемы всех ЯП не в них самих, а в программистах.

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

У многих программистов «крайним» всегда является ЯП.

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

Поздравляю.

А теперь возьмите профилировщик и посмотрите, сколько времени в процентном соотношении PHP исполняется, а сколько спит или ждет возврата управления из внешнего по отношению к нему кода.

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

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

А чем ассоциативный массив не объект с произвольными полями.

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

Речь шла об API на C++, а не PHP.

Шутка

DBF - распарсенный csv с заголовком.

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

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

ну в питоне этот __dict__ внутри объекта сахарком присыпан, да.

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

А чем ассоциативный массив не объект с произвольными полями.

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

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

Написать Лисп Питон можно на любом языке программирования)

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

Я его не очень хорошо знаю, но заявлено, что «there is no implicit conversion during construction» и «Rust doesn’t do any numeric promotions». Значит является.

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

doesn’t do any numeric promotions

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

Нету там ничего подобного?

wandrien ★★
()

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

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

Заявлено там много что. Memory safety, blazing fast, fearlessly concurrent и далее по списку. Но де-факто есть вот что:

https://godbolt.org/z/5846EqY6f


use std::ops::Deref;

struct A {}

impl A {
    fn a_fun(&self) -> () {
        println!("a_fun");
    }
}

struct B {}

impl Deref for B {
    type Target = A;

    fn deref(&self) -> &Self::Target {
        &A{}
    }
}

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

pub fn main(){
    let b = B{};
    fun(&b)
}

Вывод:

a_fun

Rust позиционирует себя как строго типизированный язык. Вы с этим либо согласны, и тогда ваши рассказы выше про имплицитный вызов эксплицитно объявленного конструктора превращаются в тыкву, либо не согласны – и тогда вы живете с тем, что ваше определение строгой типизации отличается от общепринятого.

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

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

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

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

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

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

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

Вообще умиляют эти попытки отделить C от С++ и прикрыть фиговым листочком все косяки и проблемы дизайна крестов, списывая все на сишное наследие. Типо наш бажесвиный С++ идеален, а все беды от плохой противной сишки. О том, что без сишного фундамента кресты в принципе нежизнеспособны и никогда бы не взлетели, обычно предпочитают скромно умалчивать. Чем-то напоминает тайпскриптеров, у которых тоже все зашибись, а всякие там any и прочие костыли - это все от плохого джаваскрипта, к которому они разумеется никакого отношения не имеют.

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

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

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

Потому что тип «ассоциативный массив с произвольными ключами-строками» есть, а типа «объект с классом, прочитанным из JSON» нет.

Use reflection, Luke.

import Data.Aeson
import qualified Data.ByteString.Lazy as B
import GHC.Generics

data Person = Person
  { firstName :: String,
    lastName :: String,
    age :: Int
  }
  deriving (Show, Generic, FromJSON, ToJSON)

main = do
  contents <- B.readFile "input.json"
  let person = decode contents :: Maybe Person
  print person

Тип «запись, прочитанная из JSON» есть, а типа «ассоциативный массив с произвольными ключами-строками» - нет.

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

from dataclasses import dataclass
import json

@dataclass
class Person:
    first_name: str
    last_name: str
    age: int

file = open("input.json")
obj = json.load(file)
person = Person(obj["firstName"], obj["lastName"], obj["age"])
print(person)

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

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

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

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

плюс операторы преобразования типов можно разрешать, запрещать.

alysnix ★★★
()

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

ИМХО если алгоритм выполняется за приемлемое время и клиент доволен, то всё ok!
В основном всё зависит от объёма, обрабатываемых данных.
Чисто «теоретически» вопрос интересен.

Вот при разработке системного API всё должно быть «чики чики».

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

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

что пока что не есть общее место в деве С++

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

плюс операторы преобразования типов можно разрешать, запрещать.

Как мне запретить оператор каста int в long long или в double?

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

запретить оператор каста int в long long или в double

А что такого? Вот в обратную сторону да, хотя компилятор, наверное, выдаст ворнинг.
Хуже когда бул в инт или инт в бул.

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

а типа «объект с классом, прочитанным из JSON»

И слава богу что нет (и не будет). Потому что потом начнется всрань с «классом прочитанным из XML», «классом прочитанным из YML», «классом прочитанным из БД» и прочей хренью.

Поэтому выкинуть манипуляции с построением объектов в отдельные классы (так нелюбимые многими паттерны фабрик/построителей) и забыть про всю эту чушь с «классами прочитанными из …» и никогда к ней не возвращаться.

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

каст с расширением вполне легален(int->long long). непонятно зачем его запрещать. каст с сужением нелегален.

чтобы не кастовалось в double - напишите my_safe_double и используйте его.

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

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

каст с расширением вполне легален(int->long long). непонятно зачем его запрещать.

В конкретном случае не то что каст (int->long long) может быть нелегален, а даже два идентичных int-а могут быть относительно друг друга нелегальны. Мили vs километры. Или секунды vs люмены.

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

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

https://broberts.io/StrongType/

погуглите вокруг «strong type c++», я дал просто первое что выскочило.

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

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

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

В вебне похер на время выполнения. Тут время чтения из сокета все нивелирует, поэтому никому не нужны сишка и даже богомерзкие раст с го. Да и джава тоже как правило говно мамонта какое родом из 90-х. Хомепаге начал захватывать сервера с 2003-2004, а питон открыли в 2008, когда гугл заявил об его массовом использовании, потом были раби и нода, позже всякие эликсиры… И рабисты ушли в питон, кстати. Потому как раби прибит к рельсам, а не так активно развиваются + нет альтернатив + сам язык тоже затормозил развитие. Никого не волнует скорость, абсолютно никого, проще докупить сервак чем нанимать доп программиста. Рыночнк порешал. Если бы труд погромиста оплачивался как миска риса, а серваки были на вес золота, вот это был бы идеальный мир для статистодрочеров тупизированных

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

кстати можно покомпактней сделать использование таких «сильных типов». вместо as_base как в предложенной ссылке, определить оператор () - переменная строгого типа выдает значение базового типа.

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

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

Хотя я находил сайты 95-го года примерно. Они написаны на perl и функционируют до сих пор. А что касается заявлений, что ничего крупного на питоне нельзя писать. Яндекс был взломан, 40 гигов исходников утекли в сеть. Я их изучил и там все, абсолютно все написано на питоне, на сишке только какая-то часть поискового движка, но не забываем, что писать его начали лет 25 назад

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

то и кресты в целом являются слабо типизированными.

Где-то утверждалось обратное?

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

Где это утверждалось?

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

в крестах все строго, кроме мелочей.

Мелочи - это как я понимаю все примитивные сишные типы аля char, int, float и т.д., без которых не обходится ни одна крестопрограмма? :D

Если ты считаешь, что в C/C++ строгая статическая типизация, тогда назови язык, где по твоему мнению слабая статическая типизация. Или у тебя вообще любые статически типизированные языки являются строгими, даже включая сишку с крестами?

Для справки, общепринятое понятие выглядит примерно так:

A weakly typed language has looser typing rules and may produce unpredictable or even erroneous results or may perform implicit type conversion at runtime.

https://en.wikipedia.org/wiki/Strong_and_weak_typing

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

Java, C#, Ada, and Pascal are sometimes said to be more strongly typed than C, a claim that is probably because C supports more kinds of implicit conversions, and allows pointer values to be explicitly cast while Java and Pascal do not.
archie
()
Ответ на: комментарий от arkhnchul

да, тогда иди и разберись

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

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

Java, C#, Ada, and Pascal are sometimes said to be more strongly typed than C, a claim that is probably because C supports more kinds of implicit conversions, and allows pointer values to be explicitly cast while Java and Pascal do not.

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

Если ты считаешь, что в C/C++ строгая статическая типизация,…

я о си не говорил. я вижу разницу между С и С++.

короче с кем вы там спорите - непонятно

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

Ничего не забыл?

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

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

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

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