Подтвердить что ты не робот

Почему динамический ввод так часто ассоциируется с интерпретируемыми языками?

Простые люди: я много программировал (профессионально и лично) на скомпилированных языках, таких как С++/Java, и в интерпретируемых языках, таких как Python/Javascript. Я лично считаю, что мой код почти всегда более устойчив, когда я программирую на статически типизированных языках. Однако почти каждый интерпретируемый язык, с которым я сталкиваюсь, использует динамическую типизацию (PHP, Perl, Python и т.д.). Я знаю, почему скомпилированные языки используют статическую типизацию (большую часть времени), но я не могу понять отвращение к статической типизации в интерпретируемом языке.

Почему крутое отключение? Является ли это частью характера интерпретируемых языков? ООП?

4b9b3361

Ответ 1

Интересный вопрос. BTW, я автор/сопровождающий phc (компилятор для PHP), и я делаю свою кандидатуру на компиляторы для динамических языков, поэтому я надеюсь, что я могу предложить некоторые идеи.

Я думаю, что здесь ошибочное предположение. Авторы PHP, Perl, Python, Ruby, Lua и т.д. Не разрабатывали "интерпретируемые языки", они разрабатывали динамические языки и реализовывали их с помощью интерпретаторов. Они сделали это, потому что переводчики гораздо проще писать, чем компиляторы.

Первая реализация Java была интерпретирована, и это статически типизированный язык. Интерпретаторы существуют для статических языков: у Haskell и OCaml есть переводчики, и раньше был популярным интерпретатором для C, но это было давно. Они популярны, потому что они позволяют REPL, что облегчает процесс разработки.

Тем не менее, существует отвращение к статической типизации в сообществе динамического языка, как и следовало ожидать. Они считают, что системы статического типа, предоставляемые C, С++ и Java, являются подробными и не стоят усилий. Думаю, я с этим согласен. Программирование на Python намного интереснее, чем С++.

Чтобы адресовать точки других:

  • dlamblin говорит: "Я никогда не чувствовал, что есть что-то особенное в компиляции или интерпретации, которая предложила динамику по статическому типу". Ну, ты очень неправ. Компиляция динамических языков очень сложна. В основном используется оператор eval, который широко используется в Javascript и Ruby. phc компилирует PHP раньше времени, но нам все равно нужен интерпретатор времени выполнения для обработки eval s. eval также не может быть проанализирован статически в оптимизационном компиляторе, хотя есть классная техника, если вам не нужна надежность.

  • Чтобы ответить damblin на Andrew Hare: вы могли бы, конечно, выполнить статический анализ в интерпретаторе и найти ошибки до времени выполнения, что и есть то, что Haskell ghci делает. Я ожидаю, что стиль интерпретатора, используемый в функциональных языках, требует этого. dlamblin, конечно, имеет право сказать, что анализ не является частью интерпретации.

  • Ответ Эндрю Хэра основан на неправильном допущении вопрошающих, и аналогичным образом имеет место неправильный путь. Однако он задает интересный вопрос: "Насколько сложным является статический анализ динамических языков?". Очень тяжело. В принципе, вы получите кандидатскую диссертацию о том, как это работает, и это именно то, что я делаю. Также см. Предыдущую точку.

  • Наиболее правильным ответом является Ivo Wetzel. Тем не менее, точки, которые он описывает, могут обрабатываться во время выполнения в компиляторе, и многие компиляторы существуют для Lisp и Scheme, которые имеют этот тип динамической привязки. Но, да, его сложно.

Ответ 2

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

Легче понять, считаете ли вы, что статически типизированный язык имеет компилятор, который применяет правила типа вне контекста выполнения. Интерпретированные языки никогда не анализируются статически, поэтому правила интерпретации должны выполняться интерпретатором в контексте выполнения.

Ответ 3

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

Представьте себе следующий сценарий (в Python):

import random
foo = 1

def doSomeStuffWithFoo():
    global foo
    foo = random.randint(0, 1)

def asign():
    global foo
    if foo == 1:
        return 20
    else:
        return "Test"


def toBeStaticallyAnalyzed():
    myValue = asign()

    # A "Compiler" may throw an error here because foo == 0, but at runtime foo maybe 1, so the compiler would be wrong with its assumption
    myValue += 20


doSomeStuffWithFoo() # Foo could be 1 or 0 now... or 4 ;)
toBeStaticallyAnalyzed()

Как вы можете надеяться, компилятор не имеет смысла в этой ситуации. По сути, это может предупредить вас о возможности того, что "myValue" может быть чем-то другим, кроме номера. Но тогда в JavaScript, который потерпит неудачу, потому что, если "myValue" - это String, 20 будет принудительно преобразован в String, следовательно, ошибки не произойдет. Таким образом, вы можете получить тысячи бесполезных предупреждений повсюду, и я не думаю, что это намерение компилятора.

Гибкость всегда идет с ценой, вам нужно глубже взглянуть на вашу программу или запрограммировать ее более тщательно, другими словами, вы являетесь COMPILER в таких ситуациях, как указано выше.

Итак, ваше решение как компилятор? - Исправьте его с помощью "try: except":)

Ответ 4

Компиляторы + Статические типы = эффективный машинный код
Компиляторы + Динамические типы = неэффективный машинный код

Рассмотрим следующий псевдокод:

function foo(a, b) {
    return a+b
}

Статический язык сможет знать (посредством объявления или вывода), что a и b являются целыми числами, и скомпилируются до

%reg = addi a,b

или что-то подобное, во всяком случае.

Компилятор для динамического языка должен будет генерировать код в 1. Проверьте их типы a и b
2. обрабатывать каждый случай или комбинацию случаев

%reg1 = typeof a
beq %reg1, int, a_int_case
beq %reg1, float, a_float_case
beq %reg1, string, a_string_case

label a_int_case
%reg1 = typeof b
beq %reg1, int, a_int_b_int_case
beq %reg1, float, a_int_b_float_case
beq %reg1, string, a_int_b_string_case

label a_int_b_int_case
%out = addi a,b
goto done

label a_int_b_float_case
%tmp = mkfloat a
%out = addf %tmp,b
goto done

... Etc. I can't finish

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

Так как интерпретаторы гораздо проще писать, а компиляция не приносит вам много пользы, почему бы не написать интерпретатор?

(Компиляторы "точно в срок" действительно имеют информацию о типе и могут компилироваться вплоть до одного оператора. На самом деле они имеют больше информации, чем системы статического типа, и теоретически могут сделать еще лучше. Все ассемблеры моделируются: любое сходство с реальный код, который может работать на реальной машине, является чисто случайным.)

Ответ 5

Может быть, потому, что одним из моих основных интерпретируемых языков является Perl, а один из моих скомпилированных языков - Objective-C, но я никогда не чувствовал, что есть что-то особенное в компиляции или интерпретации, которая предложила динамический статический ввод текста.

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

Я не согласен с объяснением Эндрю Харе. В то время как чисто интерпретируемый язык должен был бы добавить шаг предварительной обработки и, следовательно, не должен быть чисто интерпретирован, чтобы предупредить программиста перед выполнением ошибок статического ввода, он не исключает бросания ошибки типа во время выполнения по мере его возникновения. Поэтому отсутствие компиляции не означает, что проверка статического типа не может произойти. Но так как получение ошибки типа во время выполнения не так полезно, как получение одного при компиляции или во время проверки предполета, я вижу, как "преимущество" статического ввода в этой ситуации может показаться более неприятным, и, таким образом, выбрасываются в пользу преимуществ динамического ввода текста.

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

Процитировать статью wiki с интерпретируемыми языками. Теоретически любой язык может быть скомпилирован или интерпретирован, поэтому это обозначение применяется исключительно из-за общих практика внедрения, а не некоторое базовое свойство языка ".
Там есть хорошая статья wiki только для ввода.

Ответ 6

Я думаю, что статическая типизация упрощает компиляторы и является основной (если не только) причиной, которая присутствует на скомпилированных языках.

Для интерпретируемых языков легче предположить, что переменные не имеют типа (только значения), потому что они считаются не россыпью для данных, которые должны вписываться внутрь, а скорее для метки, которая плавает где-то в куче,

Если программист хочет, он всегда может утверждать, что переменная содержит значение заданного типа (например, при назначении). Нет оснований строить его на языке. Конечно, это не тот контроль, который у вас есть для скомпилированных языков.

Вероятно, у вас может быть язык, на котором вы должны явно объявлять тип каждой переменной, но если вам не намного проще делать интересные вещи, которые при статической типизации потребуют от программиста очень тщательно созданных сложных генерических типов.

С другой стороны. Вы знаете какой-либо динамически типизированный скомпилированный (статически, а не JIT) язык?