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

В C#

        Random random = new Random((int)DateTime.Now.Ticks);

        OrderedDictionary od = new OrderedDictionary();

        od.Add("abc", 1);
        od.Add("def", 2);
        od.Add("ghi", 3);
        od.Add("jkl", 4);


        int randomIndex = random.Next(od.Count);

        Console.WriteLine(od[randomIndex]);

        // Can access via index or key value:
        Console.WriteLine(od[1]);
        Console.WriteLine(od["def"]);
40
задан Suraj Jain 12 January 2017 в 11:24
поделиться

6 ответов

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

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

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

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

Обращаясь к мнению других:

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

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

  • Ответ Эндрю Хара основан на неверном предположении вопрошающего, и точно так же все обстоит не так. Однако он поднимает интересный вопрос: « Также см. Предыдущий пункт.

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

48
ответ дан 27 November 2019 в 01:48
поделиться

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

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

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

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

1
ответ дан 27 November 2019 в 01:48
поделиться

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

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

4
ответ дан 27 November 2019 в 01:48
поделиться

Я думаю, это из-за природы интерпретируемых языков, они хотят быть динамическими, поэтому вы МОЖЕТЕ изменить вещи во время выполнения. Из-за этого компилятор никогда точно не знает, в каком состоянии программа после того, как следующая строка кода была исключена.

Представьте себе следующий сценарий (на 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 может быть чем-то другим, кроме Number. Но тогда в JavaScript это не удастся, потому что, если myValue является String, 20 также будет неявно преобразован в String, поэтому ошибки не произойдет. Таким образом, вы можете получать тысячи бесполезных предупреждений повсюду, и я не думаю, что это предназначено для компилятора.

Гибкость всегда имеет свою цену, вам нужно глубже взглянуть на свою программу, или запрограммируйте его более тщательно, другими словами, вы являетесь КОМПИЛЯТОРОМ в подобных ситуациях.

Итак, ваше решение в качестве компилятора? - Исправьте это с помощью "попробуйте: except":)

4
ответ дан 27 November 2019 в 01:48
поделиться

Потому что стандарт C так говорит, и он получает единственный голос.

И стандарт, вероятно, правильный, потому что sizeof принимает тип и

В целом , если домен или codomain (или оба) функции содержат элементы, значительно более сложные, чем действительные числа, эта функция называется оператором. И наоборот, если ни область, ни область значений функции не содержат элементов более сложных, чем действительные числа, эта функция, вероятно, будет называться просто функцией. Тригонометрические функции, такие как косинус, являются примерами последнего случая.

Кроме того, когда функции используются так часто, что они развиваются быстрее или легче, чем общая форма F (x, y, z, ...), в результате специальные формы также называются операторами. Примеры включают инфиксные операторы, такие как сложение "

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

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

-2
ответ дан 27 November 2019 в 01:48
поделиться

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

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

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

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

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

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

2
ответ дан 27 November 2019 в 01:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: