Ну, и то, и другое очень и очень очень неправильно понято, а также две совершенно разные вещи. , которые не являются взаимоисключающими .
Статические типы являются ограничением грамматики языка. Строго типизированные языки строго можно сказать, что они не являются контекстно-свободными. Простая истина в том, что становится неразумно выражать язык разумно в контекстно-свободных грамматиках, которые не обрабатывают все свои данные просто как битовые векторы. Системы статических типов являются частью грамматики языка, если таковые имеются, они просто ограничивают ее больше, чем могла бы сделать контекстно-свободная грамматика, поэтому грамматические проверки происходят в два прохода над источником. Статические типы соответствуют математическому понятию теории типов, теория типов в математике просто ограничивает законность некоторых выражений. Мол, я не могу сказать 3 + [4,7]
по математике, это из-за теории типов этого.
Таким образом, статические типы не являются способом «предотвращения ошибок» с теоретической точки зрения, они являются ограничением грамматики. Действительно, при условии, что +, 3 и интервалы имеют обычные теоретические определения множеств, если мы удалим систему типов 3 + [4,7]
, получим довольно хорошо определенный результат, который является множеством. «ошибок типа времени выполнения» теоретически не существует, практическое использование системы типов заключается в предотвращении операций, которые для людей не имели бы смысла. Конечно, операции - это всего лишь сдвиг и манипулирование битами.
Подвох в том, что система типов не может решить, будут ли такие операции выполняться или нет, будет ли разрешено выполнение. Например, точно разделите множество всех возможных программ на те, которые будут иметь «ошибку типа», и те, которые не имеют. Это может сделать только две вещи:
1: доказать, что ошибки типа будут происходить в программе
2: доказать, что они не появятся в программе
Может показаться, что я противоречу себе. Но что делает средство проверки типов C или Java, так это то, что оно отклоняет программу как «неграмотную», или как она называет это «ошибкой типа», если она не может преуспеть в 2. Она не может доказать, что это не так. Это не произойдет, это не значит, что они не произойдут, это просто означает, что это не может доказать. Вполне возможно, что программа, у которой не будет ошибки типа, отклоняется просто потому, что она не может быть доказана компилятором. Простым примером является if(1) a = 3; else a = "string";
, конечно, поскольку это всегда так, ветвь else никогда не будет выполняться в программе, и ошибка типа не возникнет. Но он не может доказать эти случаи в общем виде, поэтому он отклонен. Это главная слабость многих статически типизированных языков: если вы защищаете себя от себя, вы также обязательно защищены в тех случаях, когда вам это не нужно.
Но, вопреки распространенному мнению, существуют также статически типизированные языки, которые работают по принципу 1. Они просто отвергают все программы, которые могут доказать, что это вызовет ошибку типа, и пропускают все программы, которые они не могут , Поэтому возможно, что они разрешают программам, в которых есть ошибки типов, хорошим примером является Typed Racket, это гибрид между динамической и статической типизацией. А некоторые утверждают, что в этой системе вы получаете лучшее из обоих миров.
Другое преимущество статической типизации состоит в том, что типы известны во время компиляции, и, таким образом, компилятор может использовать это. Если в Java мы делаем "string" + "string"
или 3 + 3
, то оба +
токена в тексте в конце представляют совершенно разные операции и данные, и компилятор знает, какой из этих типов выбрать один.
Теперь я собираюсь сделать очень спорное утверждение здесь, но иметь со мной: «динамическая типизация» не существует 1032 *.
Звучит очень спорный, но это правда, динамически типизированных языков с теоретической точки зрения нетипизированным . Это просто статически типизированные языки только одного типа. Проще говоря, это языки, которые действительно грамматически генерируются грамматикой без контекста на практике.
Почему у них нет типов? Поскольку каждая операция определена и разрешена для каждого операнда, что именно является «ошибкой типа времени выполнения»? Это из теоретического примера чисто побочный эффект . Если выполнение print("string")
, которое печатает строку, является операцией, то так же происходит и с length(3)
, первый имеет побочный эффект записи string
в стандартный вывод, второй просто error: function 'length' expects array as argument.
, вот и все. С теоретической точки зрения нет такого понятия, как динамически типизированный язык. Они нетипизированы
Хорошо, очевидное преимущество «динамически типизированного» языка - выразительная сила, а система типов - не что иное, как ограничение выразительной силы. И вообще, языки с системой типов действительно будут иметь определенный результат для всех тех операций, которые недопустимы, если система типов просто игнорируется, результаты просто не будут иметь смысла для людей. Многие языки теряют свою полноту по Тьюрингу после применения системы типов.
Очевидным недостатком является тот факт, что могут происходить операции, которые приводят к результатам, которые не имеют смысла для людей. Чтобы защититься от этого, языки с динамической типизацией обычно переопределяют эти операции, вместо того, чтобы давать этот бессмысленный результат, они переопределяют его на наличие побочного эффекта выписывания ошибки и, возможно, остановки программы в целом. Это вовсе не «ошибка», фактически, языковая спецификация обычно подразумевает это, это такое же поведение языка, как и печать строки с теоретической точки зрения. Таким образом, системы типов заставляют программиста рассуждать о потоке кода, чтобы убедиться, что этого не происходит. Или действительно, причина, по которой это происходит , также может быть полезна в некоторых моментах для отладки, показывая, что это вовсе не «ошибка», а четко определенное свойство языка. По сути, единственный остаток «динамической типизации», который есть в большинстве языков, защищает от деления на ноль. Вот что такое динамическая типизация: нет типов, нет больше типов, чем тот, что ноль отличается от всех остальных чисел. То, что люди называют «типом», - это просто еще одно свойство элемента данных, например длина массива или первый символ строки. И многие динамически типизированные языки также позволяют записывать такие вещи, как "error: the first character of this string should be a 'z'"
.
Другое дело, что языки с динамической типизацией имеют тип, доступный во время выполнения, и обычно могут проверить его, разобраться с ним и принять решение. Конечно, в теории это ничем не отличается от доступа к первому символу массива и просмотра, что это такое. Фактически, вы можете создать свой собственный динамический C, просто используйте только один тип, например long long int, и используйте его первые 8 бит для хранения вашего «type» и соответственно написания функций, которые проверяют его и выполняют добавление с плавающей запятой или целочисленное. У вас есть статически типизированный язык с одним типом или динамический язык.
На практике все это показывает, статически типизированные языки обычно используются в контексте написания коммерческого программного обеспечения, тогда как динамически типизированные языки обычно используются в контексте решения некоторых проблем и автоматизации некоторых задач. Написание кода на статически типизированных языках просто занимает много времени и обременительно, потому что вы не можете делать то, что, как вы знаете, получится, но система типов все еще защищает вас от ошибок, которые вы не делаете. Многие кодеры даже не осознают, что они делают это, потому что это в их системе, но когда вы кодируете на статических языках, вы часто обходите стороной тот факт, что система типов не позволит вам делать то, что не может пойти не так, потому что это не могу доказать, что это не пойдет не так.
Как я отмечал, «статически типизированный» в общем случае означает случай 2, виновный до тех пор, пока не доказано невиновность. Но некоторые языки, которые вообще не выводят свою систему типов из теории типов, используют правило 1: невиновен до тех пор, пока его вина не доказана, что может быть идеальным гибридом. Так что, может быть, Typed Racket для вас.
Также, для более абсурдного и экстремального примера, я в настоящее время реализую язык, где «типы» действительно являются первыми символами массива, это данные, данные типа, типа. который сам является типом и датумом, единственным датумом, который имеет себя как тип. Типы не являются конечными или статически ограниченными, но новые типы могут генерироваться на основе информации времени выполнения.