Это требование по Aleks Бромфилд гласит:
Почти каждый язык со статической системой типов также имеет динамическую систему типов. Помимо C, я не могу думать об исключении
Это действительная претензия? Я понимаю, что с классами Reflection или Loading во время выполнения Java выглядит примерно так - но можно ли распространить эту идею «постепенной типизации» на большое количество языков?
languages
dynamic-typing
static-typing
Hawkeye
источник
источник
Ответы:
Оригинальный твитер здесь. :)
Прежде всего, я несколько удивлен / шокирован тем, что мой твит воспринимается так серьезно! Если бы я знал, что это будет широко распространено, я бы потратил бы больше 30 секунд на его написание!
Тиаго Сильва справедливо указывает на то, что «статические» и «динамические» более точно описывают проверку типов , а не системы типов . На самом деле, не совсем точно сказать, что язык статически или динамически типизирован. Скорее, язык имеет систему типов, и реализация этого языка может принудительно применять систему типов с использованием статической проверки, или динамической проверки, или обоих, или ни того, ни другого (хотя это не было бы очень привлекательной реализацией языка!).
Как это бывает, существуют определенные системы типов (или особенности систем типов), которые более поддаются статической проверке, и есть определенные системы типов (или особенности систем типов), которые более поддаются динамической проверке. Например, если ваш язык позволяет вам указать в тексте программы, что конкретное значение всегда должно быть массивом целых чисел, тогда довольно просто написать статическую проверку для проверки этого свойства. И наоборот, если в вашем языке есть подтипы, и если он допускает понижение версии, тогда достаточно просто проверить достоверность понижения во время выполнения, но это чрезвычайно сложно сделать во время компиляции.
Что я действительно имел в виду под своим твитом, так это то, что подавляющее большинство языковых реализаций выполняет некоторую динамическую проверку типов. Или, что то же самое, подавляющее большинство языков имеют некоторые особенности, которые сложно (если не невозможно) проверить статически. Даункинг является одним из примеров. Другие примеры включают арифметическое переполнение, проверку границ массива и проверку нуля. Некоторые из них могут быть статически проверены при некоторых обстоятельствах, но в целом вам будет сложно найти языковую реализацию, которая не выполняет никакой проверки во время выполнения.
Это неплохая вещь. Это просто наблюдение, что есть много интересных свойств, которые мы бы хотели, чтобы наши языки применяли, и что мы не знаем, как проверять статически. И это напоминание о том, что различия, такие как «статические типы» и «динамические типы», далеко не так очевидны, как некоторые люди могут поверить. :)
Последнее замечание: термины «сильный» и «слабый» на самом деле не используются в сообществе исследователей языка программирования, и они не имеют постоянного значения. В общем, я обнаружил, что когда кто-то говорит, что у языка есть «строгая типизация», а у какого-то другого языка есть «слабая типизация», они действительно говорят, что их любимый язык (язык с «строгой типизацией») не позволяет им делая некоторую ошибку, что другой язык (язык со «слабой типизацией») не делает - или наоборот, что их любимый язык (язык со «слабой типизацией») позволяет им делать что-то классное, что другой язык ( один с "строгой типизацией") нет.
источник
Ну да. Вы можете иметь сумки с имуществом на любом статически типизированном языке. Синтаксис будет ужасным, и в то же время вы получите все недостатки динамически типизированной системы. Таким образом, в действительности нет никаких преимуществ, если компилятор не позволяет использовать более приятный синтаксис, как
dynamic
это делает C # with .Кроме того, вы можете сделать это довольно легко в C тоже.
В ответ на другие ответы: я думаю, что люди ошибочно принимают статическую / динамическую типизацию с сильной / слабой типизацией. Динамическая типизация подразумевает возможность изменять структуру данных во время выполнения, а код - использовать данные, которые просто соответствуют потребностям кода. Это называется Duck Typing .
Упоминание рефлексии не рассказывает всей истории, потому что рефлексия не позволяет вам изменить существующую структуру данных. Вы не можете добавить новое поле в класс или структуру в C, C ++, Java или C #. В динамических языках добавление новых полей или атрибутов в существующие классы не только возможно, но на самом деле довольно распространено.
Например, посмотрите на Cython , компилятор Python-to-C. Он создает статический C-код, но система типов по-прежнему сохраняет свою динамическую природу. C - статически типизированный язык, но он может поддерживать динамическую типизацию из Python.
источник
ExpandoObject
, хотя это очень многообещающий процесс, во многом в отличие от JavaScript или Ruby. Тем не менее, вы сделали очень важный вывод: «Утиная печать» (что на самом деле имеют в виду 99% разработчиков, когда говорят «динамически печатать») и рефлексия - это совсем не одно и то же.True
, чтобы сказать «этот сумасшедший объект является экземпляром класса, который я определяю»). Насколько я понимаю, у OCaml есть эта особенность, но я на самом деле не знаю.Динамические языки являются статическими языками . То, что обычно называют «динамической типизацией», на самом деле представляет собой особый случай статической типизации - случай, когда вы ограничиваете себя только одним типом. В качестве мысленного эксперимента представьте, что вы пишете программу на Java или C #, используя только
Object
переменные / поля / параметры, и преобразуете код непосредственно перед вызовом любого метода. Было бы точнее называть такие языки, как Python или Javascript, «единой формой». (Это утверждение, вероятно, смущает / беспокоит многих людей, учитывая, что такая программа на Java или C # будет использовать много подтипов, но это потому, что средний язык ООП объединяет типы и классы. Для получения более подробной информации прочтите сообщение в блоге.)Обратите внимание, что даже C имеет «динамическую» типизацию - вы можете привести любой указатель к указателю
void
(и, если мне неchar
изменяет память ) и обратно. И обратите внимание, также, что там нет проверки во время выполнения; если вы ошибаетесь, наслаждайтесь своим неопределенным поведением!источник
String foo = (String) bar
что это не означает, чтоbar
это на самом делеString
. Вы можете точно знать это только во время выполнения, поэтому я не вижу, как приведение происходит «статически».dynamic
объект для этого. Если вы попытаетесь добавить свойство кobject
... ну, вы не сможете.Разница между статической и динамической типизации является , когда тип значения проверяется: время компиляции время против запуска. В языках, где значения несут свой тип с собой (например, объекты Java), вы всегда можете прибегнуть к динамической типизации, даже если язык фактически предпочитает статическую типизацию. Вот пример в Java с динамически типизированным методом:
Обратите внимание, как тип каждого элемента проверяется во время выполнения. Эквивалентно статически типизированный метод:
В C значения (и, в частности, указатели) не сохраняют свой тип во время выполнения - каждый указатель эквивалентен a
void *
. Вместо этого переменные и выражения имеют тип. Чтобы добиться динамической типизации, вы должны носить информацию о типе самостоятельно (например, как поле в структуре).источник
frobnicate
метод здесь без предварительного знания оSpecificType
.dynamic
ключевым словом). Приравнивание статического к времени компиляции и динамического к времени выполнения в основном просто мутит воду.[1,2].Add([3,4])
уступить[1,2,3,4]
,[1,2,[3,4]]
или[4,6]
?Add
в массиве нет метода, принимающего массив, потому что такой метод был бы неоднозначным. Утиная печать не освобождает вас от написания понятных типов и функций.Статическая и динамическая типизация в основном относится к тому, как проверяются типы. Статическая типизация означает, что проверка типов различных переменных или выражений проверяется на основе фактического кода (обычно компилятором), тогда как в динамической системе типов эта проверка выполняется только во время выполнения, средой выполнения.
Я полагаю, что текст ссылается на то, что даже если типы проверяются статически, они также проверяются во время выполнения, то есть динамически. Вы правильно упомянули Java Reflection; отражение происходит только во время выполнения, и среда выполнения Java (JVM) фактически выполняет проверку типов при использовании отражения, что в основном означает динамическую проверку типов.
источник
Исключение неверно: C также имеет важную динамическую систему типов. Он просто не проверяет это («C строго типизирован, слабо проверен»). Например, обработка структуры как
double
(reinternpret_cast
-стиля) приводит к неопределенному поведению - ошибка динамического типа.источник