Несколько причин:
- более быстрый цикл разработки, запись-тест против запись-компиляция-ссылка-тест
- проще организовать динамическое поведение (отражение, метапрограммирование)
- делает всю систему переносимой (просто перекомпилируйте базовый код C, и вы можете перейти на новую платформу)
Подумайте, что произойдет, если система будет не интерпретирована. Скажем, вы использовали перевод на C в качестве механизма. Скомпилированный код должен периодически проверять, не был ли он заменен метапрограммированием. Аналогичная ситуация возникает с функциями eval()
-типа. В этих случаях ему придется снова запускать компилятор, крайне медленный процесс, или же также *1019* должен иметь интерпретатор во время выполнения в любом случае.
Единственная альтернатива здесь - это JIT-компилятор. Эти системы являются очень сложными и сложными и имеют даже большие следы времени выполнения, чем все другие альтернативы. Они запускаются очень медленно, что делает их непрактичными для написания сценариев. Вы когда-нибудь видели скрипт Java? У меня нет.
Итак, у вас есть два варианта:
- все недостатки как компилятора, так и интерпретатора
- только недостатки переводчика
Не удивительно, что, как правило, основная реализация просто идет со вторым выбором. Вполне возможно, что когда-нибудь мы увидим вторичные реализации, такие как компиляторы. Ruby 1.9 и Python имеют виртуальные машины с байт-кодом; это так и есть. Компилятор может предназначаться только для нединамического кода, или он может иметь различные уровни поддержки языка, объявленные как опции. Но поскольку такая вещь не может быть первичной реализацией, она представляет собой большую работу для очень незначительной выгоды. В Ruby уже есть 200 000 строк C ...
Полагаю, мне следует добавить, что всегда можно добавить скомпилированное расширение C (или, с некоторым усилием, любой другой язык). Итак, скажем, у вас есть медленная числовая операция. Если вы добавите, скажем, Array#newOp
с реализацией C, тогда вы получите ускорение, программа останется в Ruby (или как угодно), и ваша среда получит новый метод экземпляра. Все побеждают! Таким образом, это уменьшает потребность в проблемной вторичной реализации.