Постепенная типизация — это система типов , которая находится между статической типизацией и динамической типизацией . Некоторым переменным и выражениям могут быть назначены типы, и правильность типизации проверяется во время компиляции (что является статической типизацией ), а некоторые выражения могут оставаться нетипизированными, и возможные ошибки типов сообщаются во время выполнения (что является динамической типизацией ).
Постепенная типизация позволяет разработчикам программного обеспечения выбирать любую подходящую парадигму типа в пределах одного языка. [1] Во многих случаях постепенная типизация добавляется к существующему динамическому языку, [2] создавая производный язык, позволяющий, но не требующий использования статической типизации. В некоторых случаях язык использует постепенную типизацию с самого начала.
Термин был придуман Джереми Сиком, который разработал метод постепенной типизации в 2006 году совместно с Валидом Тахой. [1] [ необходим неосновной источник ]
В постепенной типизации специальный тип, называемый dynamic, используется для представления статически неизвестных типов. Понятие равенства типов заменяется новым отношением, называемым conformity , которое связывает динамический тип с любым другим типом. Отношение conformity является рефлексивным и симметричным, но не транзитивным. [3]
Предыдущие попытки интеграции статической и динамической типизации пытались сделать динамический тип как верхним, так и нижним в иерархии подтипов. Однако, поскольку подтипирование является транзитивным, это приводит к тому, что каждый тип становится связанным с каждым другим типом, и поэтому подтипирование больше не исключает никаких статических ошибок типов. Добавление второй фазы проверки правдоподобности в систему типов не решило эту проблему полностью. [4] [5]
Постепенная типизация может быть легко интегрирована в систему типов объектно-ориентированного языка, который уже использует правило подчинения , чтобы разрешить неявные преобразования относительно подтипирования. Основная идея заключается в том, что согласованность и подтипирование являются ортогональными идеями, которые прекрасно сочетаются. Чтобы добавить подтипирование к постепенно типизированному языку, просто добавьте правило подчинения и правило подтипирования, которое делает динамический тип подтипом самого себя, поскольку подтипирование должно быть рефлексивным. (Но не делайте верхнюю часть порядка подтипирования динамической!) [6]
Примерами постепенно типизированных языков, полученных из существующих динамически типизированных языков, являются Closure Compiler , TypeScript (оба для JavaScript [7] ), [8] Hack (для PHP), PHP (с версии 7.0 [9] ), Typed Racket (для Racket [10] [11] ), Typed Clojure (для Clojure ), [12] Cython ( компилятор Python ), mypy (статическая проверка типов для Python ), [13] pyre (альтернативная статическая проверка типов для Python), [14] или cperl (типизированный Perl 5 ). ActionScript — это постепенно типизированный язык [15] , который сейчас является реализацией ECMAScript , хотя изначально он возник отдельно как родственный язык, оба под влиянием HyperTalk от Apple .
Была разработана система для языка программирования J [16], добавляющая приведение, распространение ошибок и фильтрацию к обычным свойствам проверки системы типов, а также применение функций типов вне определений функций, тем самым увеличивая гибкость определений типов.
Напротив, C# изначально был статически типизированным языком, но начиная с версии 4.0 стал постепенно типизированным, что позволяет явно помечать переменные как динамические с помощью типа dynamic
. [17] Постепенно типизированные языки, не являющиеся производными от динамически типизированных языков, включают Dart , Dylan и Raku .
Raku (ранее Perl6) имеет постепенную типизацию, реализованную с самого начала. Проверки типов происходят во всех местах, где значения назначаются или связываются. «Нетипизированная» переменная или параметр типизируется как Any
, что будет соответствовать (почти) всем значениям. Компилятор отмечает конфликты проверки типов во время компиляции, если он может определить во время компиляции, что они никогда не будут успешными.
Objective-C имеет постепенную типизацию для указателей объектов относительно вызовов методов. Статическая типизация используется, когда переменная типизирована как указатель на определенный класс объектов: когда выполняется вызов метода для переменной, компилятор статически проверяет, что класс объявлен для поддержки такого метода, или он генерирует предупреждение или ошибку. Однако, если id
используется переменная типа, компилятор разрешит вызывать любой метод для нее.
Язык программирования JS++ , выпущенный в 2011 году, представляет собой надмножество JavaScript (динамически типизированное) с постепенной системой типов, которая подходит для особых случаев ECMAScript и DOM API. [18]