У вашего вопроса есть несколько аспектов.
Во-первых, я скажу, что комбинация статически типизированного кода с интерпретируемой динамической средой выполнения является наиболее распространенной в качестве дополнительного решения к существующему динамическому языку. JavaScript, Python и Racket / Scheme / Lisp имеют варианты со статической проверкой типов *. Тем не менее, все они по-прежнему используют среду выполнения исходного языка. Статический тип проверка дает значение программисту, даже если информация статического типа фактически не используется механизмом выполнения.
Второй аспект, я думаю, может относиться к приведенному вами определению. В то время как некоторые статические языки отбрасывают информацию о типе при компиляции и используют ее только для того, чтобы код не проверял типы, другие, такие как Java и C #, также сохраняют информацию о типе для использования во время выполнения. Что делает статическую проверку типов статической, так это то, что ее можно выполнять без выполнения кода. Дополнительные проверки могут выполняться во время выполнения (например, что приводит к исключению ClassCastException в Java), но тогда это проверка динамического типа (выполняется на основе информации из статически типизированного кода).
Что касается преимущества фактического создания интерпретируемой реализации для статически типизированного языка: компиляторы - это сложно. Не так сложно, как раньше (например, с появлением LLVM), но все же обычно сложнее, чем создание прототипа интерпретируемой среды выполнения. Если вы экспериментируете с расширенными системами типов, возможно, будет проще интерпретировать первую реализацию. Если тип проверяется статически, у вас будет отдельная фаза проверки типа без выполнения кода. Это потенциально может заставить среду выполнения не беспокоиться о проверке типов во время фактического выполнения кода.
*: TypeScript, Flow, mypy и Typed Racket, чтобы упомянуть некоторые из них.
Изменить: пример, упомянутый в комментарии. Standard ML of New Jersey (SML / NJ) - это интерпретатор статически типизированного языка Standard ML. Возьмем следующую очень простую программу:
val _ = print "hello\n";
val foo : string = 4;
В SML / NJ каждый оператор проверяется на тип, а затем оценивается отдельно в существующей среде типов, прежде чем перейти к следующему оператору. Таким образом, весь код проверяется по типу перед его выполнением, но вышеуказанная программа все равно будет печатать приветствие до сбоя. Однако следующая программа ничего не печатает:
val foo : int = print "hello\n";
Он не печатает hello, а затем пытается сохранить nil в foo. Он терпит неудачу перед этим на отдельной фазе проверки типа.
person
Erik Vesteraas
schedule
16.07.2016