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

11

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

KL
источник

Ответы:

11

Насколько мне известно, нет такой вещи, как интерпретируемый «язык» или скомпилированный «язык».

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

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

Например, вы можете использовать компилятор JRuby для более легкой интеграции с библиотеками Java вместо интерпретатора ruby ​​MRI. Вероятно, есть также причины использовать интерпретатор MRI ruby ​​над JRuby, хотя я не знаком с языком и не могу говорить с этим.

Предлагаемые преимущества переводчиков:

  • Отсутствие компиляции означает, что время от редактирования кода до тестирования приложения может быть уменьшено
  • Нет необходимости создавать двоичные файлы для нескольких архитектур, потому что интерпретатор будет управлять абстракцией архитектуры (хотя вам, возможно, придется по-прежнему беспокоиться о сценариях, корректно обрабатывающих целые размеры, а не о бинарном распределении)

Предлагаемые преимущества компиляторов:

  • Скомпилированный нативный код не имеет накладных расходов интерпретатора и поэтому обычно более эффективен во времени и пространстве
  • Функциональная совместимость обычно лучше, единственный способ взаимодействия внутри скрипта со скриптами - через интерпретатора, а не стандартную FFI
  • Возможность поддержки архитектур, для которых интерпретатор не был скомпилирован (например, встроенные системы)

Тем не менее, я бы поспорил, что в 90% случаев это выглядит примерно так : я хочу написать это программное обеспечение в blub, потому что я хорошо его знаю и оно должно хорошо работать. Я буду использовать интерпретатор blub (или компилятор), потому что это общепринятый канонический метод написания программного обеспечения в blub.

Таким образом, TL; DR - это, в основном, индивидуальное сравнение интерпретаторов и компиляторов для вашего конкретного варианта использования.

Кроме того, FFI: Интерфейс внешних функций, другими словами, интерфейс для взаимодействия с другими языками. Больше чтения в википедии

Джимми Хоффа
источник
2
Насколько мне известно, некоторые языки сценариев для ОС, такие как ksh для UNIX, не могут быть скомпилированы.
NoChance
@delnan, я не могу скомпилировать коммерческое или бесплатное программное обеспечение, о котором я знаю, а не то, что его нельзя скомпилировать по техническим причинам.
NoChance
3
@EmmadKareem Нет такой вещи, как «не может быть скомпилировано». Вы пишете программу, которая читает программу на языке Li и выводит эквивалентную программу на языке La. Это компилятор и компилятор. Я не решаюсь вызывать аргумент полноты тьюринга, поскольку на практике это красная сельдь, но каждая программа в конечном итоге превращается в последовательность инструкций машинного кода. Если ничего не помогает, разверните цикл интерпретатора (и упростите полученный код, чтобы удалить части, которые вам больше не нужны). Если переводчик написан на языке без переводчиков, повторяйте, пока вы не нажмете что-нибудь с помощью компилятора.
1
(Я отредактировал свой комментарий, чтобы лучше его сформулировать, но, видимо, я поступил слишком поздно.) @EmmadKareem Да, очевидно, что некоторые языки никогда не были реализованы через компилятор. Но я не понимаю, насколько это актуально. Это всегда возможно и выполнимо, и может быть сделано в любое время с некоторыми усилиями. Это является следствием основного положения, заключающегося в том, что язык не компилируется и не интерпретируется и может быть реализован обоими способами. И множеством других способов (ну, возможно, незначительные варианты и ремиксы), кстати.
2
@ EmmadKareem, если вы хотите, вы можете взять спецификацию языка ksh и написать компилятор, который читает его и генерирует собственный двоичный файл. Язык, который компилируется или интерпретируется, не входит в определение языка - вот моя точка зрения.
Джимми Хоффа
8

Важным моментом здесь является то, что многие языковые реализации фактически делают своего рода гибрид обоих. Сегодня многие широко используемые языки работают, компилируя программу в промежуточный формат, такой как байт-код, и затем выполняя его в интерпретаторе. Вот как обычно реализуются Java, C #, Python, Ruby и Lua. На самом деле, возможно, именно так реализовано большинство языков, используемых сегодня. Фактически язык сегодня интерпретирует и компилирует свой код. Некоторые из этих языков имеют дополнительный JIT-компилятор для преобразования байт-кода в собственный код для выполнения.

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

Когда вы спрашиваете о достоинствах интерпретируемых и компилируемых языков, вы, вероятно, имеете в виду что-то еще. Вы можете спросить о достоинствах статической / динамической типизации, преимуществах распространения собственных исполняемых файлов, относительных преимуществ компиляции JIT и AOT. Это все проблемы, которые связаны с интерпретацией / компиляцией, но это разные проблемы.

Уинстон Эверт
источник
2

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

Теперь, прежде чем кому-то интересно ... Да, C / C ++ / C # / Java можно интерпретировать, и да, скрипты JavaScript и Bash можно компилировать. Есть ли рабочие интерпретаторы или компиляторы для этих языков - другой вопрос.

Теперь, чтобы фактически ответить на вопрос, когда мы будем использовать «интерпретируемый язык» вместо «скомпилированного языка». Сам вопрос несколько сбивает с толку, но я предполагаю, что это означает, когда следует предпочесть интерпретацию компиляции. Одним из недостатков компиляции является то, что она генерирует некоторые издержки из-за процесса компиляции - исходный код должен быть скомпилирован в исполняемый машинный код, поэтому он не подходит для задач, которые требуют минимальной задержки при вызове исходного кода для выполнения программы. С другой стороны, скомпилированный исходный код почти всегда быстрее, чем эквивалентный интерпретируемый исходный код, из-за накладных расходов, вызванных интерпретацией кода. Переводчики, с другой стороны, могут вызывать и запускать исходный код с очень небольшими накладными расходами, но за счет производительности во время выполнения.

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

Тем не менее, есть нечто, что можно рассматривать как реальный пример: исходный код hidnig после развертывания. С роднойСкомпилированный код разработчик развертывает исполняемым программным кодом Macine и данными. При интерпретированном коде должен быть развернут сам исходный код, который затем может быть проверен и подвергнут повторному проектированию с гораздо меньшими усилиями, чем то, что требуется для обратного инжиниринга собственного машинного кода. Единственным исключением из этого являются такие языки, как C # и Java, которые компилируются в непосредственный язык / байт-код (MSIL для C # и Java-байт-код для Java), который затем развертывается и компилируется «вовремя» во время выполнения, что-то вроде интерпретатора. Однако существуют так называемые декомпиляторы для MSIL и Java Bytecode, которые могут воссоздать исходный исходный код с относительно хорошей точностью, и, таким образом, обратное проектирование таких продуктов гораздо более тривиально, чем продукты обратного проектирования, которые развернуты в собственном машинном коде.

zxcdw
источник
1
Вы делаете хорошие замечания, но, будучи педантом, я не согласен с некоторыми фразами (оба ссылаются на третий абзац): 1. Интерпретатор не компилирует. 2. Плохо (хотя эти условия встречаются редко), когда плохой неоптимизирующий компилятор будет побежден высокооптимизированным (особенно на основе байт-кода) интерпретатором. Это будет вдвойне, если вы посчитаете JIT-компиляторы по интерпретаторам (что я предпочитаю не делать, но некоторые люди так делают).
@delnan Возможно, это плохо сформулировано, я не являюсь носителем английского языка. Однако, насколько я могу судить, третий абзац не означает, что интерпретатор будет компилировать. Во-вторых, я акцентировал внимание на слове, эквивалентном акцентному подобию скомпилированного и интерпретированного кода, чтобы исключить случаи плохого компилятора и высокопроизводительного интерпретатора, возможно, я не совсем понял с этим, однако я не вижу его Разумно сосредоточиться на объяснении таких крайних случаев, поскольку это не способствует тому, что делается различие между выполнением исходного кода путем его компиляции или его
интерпретации
Извините, не говоря уже о первом пункте, я что-то неправильно понял. Моя вина. Что касается второго пункта: я взял «эквивалент» для ссылки на код, который интерпретируется или компилируется (и сравнение компилятора и интерпретатора не имеет большого смысла, так как они делают принципиально разные вещи). Я не думаю, что нужно тратить время на детализацию странных случаев, таких как мой пример, но я бы предпочел отбросить «всегда» в пользу фразы, которая объясняет, почему это может быть быстрее, во-первых: никаких накладных расходов на переводчика [что должно быть определено ИМХО], и возможность выполнять оптимизацию до выполнения.
1

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

  • Там, где нет компилятора, такого как сценарии оболочки Linux / Unix .
  • Быстрые и грязные скрипты, которые решают небольшую проблему
  • Языки, облегчающие написание динамических HTML-страниц и обычно интерпретируемые как JSP (Tomcat компилирует его в предыдущие версии для сервлеров), PHP, ASP и т. Д.

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

  • Вам нужно распространять двоичные файлы, потому что ваше приложение с закрытым исходным кодом и вы не хотите выдавать свой исходный код.
  • Скорость, как встроенные системы и тому подобное.
  • Вам нужен уровень безопасности типов кода, который может дать только компилятор со строго типизированным языком. Компиляторы раскрывают опечатки в каждом уголке исходного кода, тогда как в интерпретируемых программах опечатки могут остаться необнаруженными в производственном коде.
  • Большие , сложные системы: нельзя представить операционную систему или офисный костюм как что-либо, кроме скомпилированных двоичных файлов.
  • Вы хотите избавиться от всех проблем и нуждаетесь в хорошем взаимодействии с фрагментами ассемблера (сложно с любым временем выполнения, особенно с интерпретатором) (этот момент вызван комментарием @delnam)
Тулаинс Кордова
источник
3
Языковой переводчик делает язык не менее строго типизированным. Хаскель чрезвычайно строго типизирован, и вы можете использовать GHCI для его эффективной интерпретации. Строгая / слабая типизация - это аспекты языка, а не аспекты компилятора или интерпретатора.
Джимми Хоффа
1
-1 О преимуществах компиляции: (1) Компиляция кода не защищает от реверс-инжиниринга, а лишь усложняет его. (2) Компиляция (удаление накладных расходов интерпретатора, автоматическая оптимизация кода приложения) является лишь одним из источников производительности и превосходит ручную крупномасштабную оптимизацию, выполняемую специалистом-человеком. (3) Проверка типа, хотя обычно связана с компиляцией, не зависит от нее. Проверка типов - это проход статического анализа; это может произойти без испускания кода и до интерпретации кода. (4) Кажется довольно ложным. Вы не можете себе это представить? Зачем? Как это требуется?
1
Другие интерпретируемые языки существуют, когда есть переводчик в другой программе. Всякий раз, когда кто-то использует образец интерпретатора , существует интерпретируемый язык некоторой сложности.
3
«Сценарии» не обязательно интерпретируются. Многие языки сценариев компилируются в байт-код для виртуальной машины, которая затем выполняется (см. Lua, perl, python, ruby). Между этим и java нет никакой разницы, кроме случаев, когда происходит компиляция.
3
+1, я думаю, что это именно тот ответ, который был на самом деле после ОП, и хотя, как указывалось, баллы могут быть не на 100% верными, практические соображения верны как минимум на 95%.
Док Браун
1

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

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

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

Зная это, интерпретируемые языки подходят для:

  1. Продуктивная разработка: быстрая веб-разработка (PHP, Javascript) или для прототипирования.
  2. Кросс-платформенная; Например, JavaScript поддерживается во всех браузерах (включая мобильные).

И скомпилированные языки подходят, когда:

  1. Производительность критична (операционные системы) или ресурсы ограничены (микроконтроллеры).
  2. Системы должны быть сложными; при построении больших систем (корпоративных систем) скомпилированные языки имеют важное значение для обработки многих возможных ошибок, которые могут появляться в интерпретируемых языках; также сложные программы требуют много ресурсов, и баланс имеет тенденцию к компилируемым языкам также.
m3th0dman
источник
-1 потому что вы подразумеваете, что все интерпретируемые языки динамически типизированы, а все скомпилированные языки статически типизированы, что совершенно не соответствует действительности.
Даниэль Приден
@DanielPryden Это должно быть чистое совпадение, факт, что почти все интерпретируемые языки типизированы динамически, а скомпилированные статически типизированы? Является ли совпадением то, что модель динамического типа подходит для интерпретируемых языков?
m3th0dman
По разным причинам существует корреляция, но она не является обязательной. Это на самом деле было задано в StackOverflow: почему интерпретируемые langs в большинстве случаев являются утилитными, а компилируемые имеют строгую типизацию?
Daniel Pryden
1
Erlang компилируется и динамически печатается. Haskell типизирован статически и может быть скомпилирован или интерпретирован
Zachary K
1
@ZacharyK Erlang имеет систему времени выполнения; Haskell компилируется в большинстве случаев (программы написаны).
m3th0dman
1

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

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

Это относится, например, к языкам агентов или к тому, как, например, обычно используется Tcl / Tk.

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

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

SK-логика
источник