Скомпилированная реализация и система динамического набора языка программирования

Я просматривал этот пост о различиях между языком со статической и динамической типизацией и в комментарии к следующему определению, взятому из этого справочника:

Статическая типизация очень часто неправильно понимается как означающая, что значения связаны с типами в CompileTime, когда вместо этого это означает, что ReferenceValue явно (что не то же самое, что в CompileTime) ограничено по отношению к типу значения, которое оно может обозначать, и что языковая реализация, будь то компилятор или интерпретатор, обеспечивает и использует эти ограничения в максимально возможной степени.

Если я не ошибаюсь, в этом определении говорится, что наличие или отсутствие статической типизации не зависит от наличия (или отсутствия) скомпилированной реализации языка.

Но, говоря таким образом, в чем преимущество интерпретируемой реализации со статической типизацией? Я имею в виду, что проверка всегда выполняется во время выполнения.


person zer0uno    schedule 16.07.2016    source источник
comment
Он все равно обнаружит ошибки до того, как фактически выполнит какой-либо код.   -  person melpomene    schedule 17.07.2016
comment
Вы имеете в виду, что перед запуском первой строки кода выполняется полная проверка типа? Разве это не происходит параллельно с казнью?   -  person zer0uno    schedule 17.07.2016
comment
Перечитывая вашу цитату, я не понимаю, что она пытается сказать. Я предполагаю, что это просто неправильно.   -  person melpomene    schedule 17.07.2016


Ответы (1)


У вашего вопроса есть несколько аспектов.

Во-первых, я скажу, что комбинация статически типизированного кода с интерпретируемой динамической средой выполнения является наиболее распространенной в качестве дополнительного решения к существующему динамическому языку. 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
comment
Итак, насколько я понял, даже если есть интерпретатор, вся проверка типов выполняется для всего исходного кода? - person zer0uno; 17.07.2016
comment
Если он статически типизирован checked, тогда да, но я могу представить язык, который статически типизирован, но проверяется только тип во время выполнения (но я не знаю никаких примеров). Однако есть крайние случаи, которые стирают границы даже в случае проверки статического типа. Я добавлю пример в ответ, так как этот комментарий становится длинным. - person Erik Vesteraas; 17.07.2016