Ответ 1
Я не думаю, что здесь есть черный и белый - между динамическим и статическим существует целый спектр.
Возьмем два крайних примера для каждой стороны спектра и посмотрим, откуда это происходит.
Haskell является экстремальным в статическом направлении.
- Он имеет мощную систему типов, которая проверяется во время компиляции: если ваша программа компилируется, она не содержит общих и не очень распространенных ошибок.
- Скомпилированная форма сильно отличается от программы haskell (она является двоичной). Следовательно, отражение и модификация времени выполнения сложны, если только вы этого не предвидели. По сравнению с интерпретацией оригинала, результат потенциально более эффективен, так как компилятор может делать фанковые оптимизации.
Итак, для статических языков я обычно думаю: достаточно длительный анализ времени компиляции, система типа не позволит мне совершать глупые ошибки, а также делать некоторые вещи, которые действительно действительны, и если я хочу делать какие-либо манипуляции с программой во время выполнения это будет немного больно, потому что представление во время выполнения программы (то есть ее скомпилированная форма) отличается от самого реального языка. Кроме того, это может быть болью, чтобы изменить вещи позже, если я этого не предвидел.
Clojure является экстремальным в динамическом направлении.
- У него тоже есть система типов, но во время компиляции проверка типа отсутствует. Многие распространенные ошибки можно обнаружить только при запуске программы.
- Clojure программы по существу являются просто Clojure списками (структура данных) и могут управляться как таковые. Поэтому, когда вы выполняете отражение во время выполнения, вы фактически обрабатываете программу Clojure более или менее, так как вы ее вводите - форма выполнения очень близка к самому языку программирования. Таким образом, вы можете в основном делать то же самое во время выполнения, как вы могли бы при "типе времени". Следовательно, производительность выполнения может пострадать из-за того, что компилятор не может выполнять многие оптимизационные функции.
Для динамических языков я обычно думаю: короткий шаг компиляции (в основном, просто синтаксис чтения), настолько быстрое и инкрементное развитие, практически не ограничивает того, что это позволит мне сделать, но не помешает мне глупым ошибкам.
Как указывали другие сообщения, другие языки пытаются занять больше среднего места - например, статические языки, такие как F # и С#, предлагают возможности отражения через отдельный API и, конечно же, могут предлагать инкрементную разработку с использованием умных инструментов, таких как F # REPL. Динамические языки иногда предлагают необязательную типизацию (например, Racket, Strongtalk) и, как правило, имеют более продвинутые рамки тестирования, чтобы компенсировать отсутствие какой-либо проверки работоспособности во время компиляции. Также вводить подсказки, пока они не проверяются во время компиляции, являются полезными подсказками для создания более эффективного кода (например, Clojure).
Если вы ищете подходящий инструмент для данной проблемы, то это, безусловно, одно из тех размеров, на которые вы можете смотреть, но сам по себе вряд ли будет принимать решение в любом случае. Подумайте о других свойствах языков, которые вы рассматриваете, - это функциональный или OO, логический или... язык? У этого есть хорошая структура для вещей, в которых я нуждаюсь? Нужна ли мне стабильность и двоичная обратная совместимость, или я могу жить с некоторым оттоком в компиляторе? Нужен ли мне обширный инструментарий?