Является ли Ruby действительно интерпретируемым языком, если все его реализации скомпилированы в байт-код? - PullRequest
16 голосов
/ 04 апреля 2009

В выбранном ответе для на этот вопрос о Blue Ruby Чак говорит:

Все текущие рубины реализации скомпилированы в байткод. Вопреки утверждениям SAP, как Ruby 1.9, МРТ сама включает в себя компилятор байт-кода, хотя возможность сохранить скомпилированный байт-код на диск исчез где-то в процессе слияния виртуальной машины YARV. JRuby скомпилирован в Java .class файлы. У меня не много деталей на MagLev, но это кажется безопасным, чтобы сказать это и по этой дороге.

Я запутался в этой проблеме компиляции / интерпретации в отношении Ruby.

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

Но если все реализации Ruby теперь скомпилированы, справедливо ли все еще говорить, что Ruby является интерпретируемым языком? Или я что-то недопонимаю?

Ответы [ 7 ]

21 голосов
/ 04 апреля 2009

В настоящее время почти каждый язык "компилируется", если вы считаете, что байт-код компилируется. Даже Emacs Lisp компилируется. Ruby был особым случаем, потому что до недавнего времени не не компилировался в байт-код.

Я думаю, вы правы, ставя под сомнение полезность описания языков как "скомпилированных" и "интерпретированных". Однако одно полезное различие заключается в том, создает ли язык машинный код (например, ассемблер x86) непосредственно из пользовательского кода. C, C ++, многие Lisps и Java с включенным JIT делают, но Ruby, Python и Perl этого не делают.

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

19 голосов
/ 04 апреля 2009

Да, Ruby по-прежнему является интерпретируемым языком, или, точнее, Ruby Interpreter (MRI) Матса, о котором обычно говорят люди, когда говорят о Ruby, он все еще является переводчиком. Этап компиляции просто для того, чтобы свести код к чему-то, что выполняется быстрее, чем интерпретировать и переинтерпретировать один и тот же код раз за разом.

8 голосов
/ 02 июня 2011

Действительно тонкий вопрос ... Раньше считалось, что «интерпретируемые» языки были проанализированы и преобразованы в промежуточную форму, которая выполнялась быстрее, но «машина», выполняющая их, была довольно специфичной для языка программой. Вместо этого «скомпилированные» языки были переведены в инструкции машинного кода, поддерживаемые компьютером, на котором они выполнялись. Раннее различие было очень основным - статический и динамический объем. В статически типизированном языке ссылка на переменную может быть в значительной степени разрешена по адресу памяти в нескольких машинных инструкциях - вы точно знали, где в вызывающем кадре указана переменная. В динамически типизированных языках вы должны были искать (вверх по списку А или по вызывающему кадру) ссылку. С появлением объектно-ориентированного программирования не непосредственный характер ссылки расширился до многих других понятий - классов (типов), методов (функций), даже синтаксической интерпретации (встроенных DSL, таких как regex).

Различие, по сути, восходящее к концу 70-х годов, было не столько между скомпилированными и интерпретируемыми языками , сколько в том, были ли они запущены в скомпилированной или интерпретированной среде. Например, Паскаль (первый язык высокого уровня, который я изучил) работал в Калифорнийском университете в Беркли сначала на интерпретаторе Билла Джоя pxp , а затем на компиляторе он написал pcc . Один и тот же язык, доступный как в скомпилированной, так и в интерпретируемой среде.

Некоторые языки более динамичны, чем другие, значение чего-либо - типа, метода, переменной - зависит от среды выполнения. Это означает, что скомпилированный или нет существенный механизм времени выполнения, связанный с выполнением программы. Forth, Smalltalk, NeWs, Lisp, все были примерами этого. Первоначально эти языки требовали так много механизмов для выполнения (по сравнению с C или Fortran), что они были естественными для интерпретации.

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

Я думаю, что это была Java, которая была первым широко распространенным языком, который действительно запятнал пробел в компиляторе / интерпретаторе, по иронии судьбы не так, чтобы он работал быстрее (хотя и это тоже), но так, чтобы он работал везде. Определив свой собственный машинный язык и «машинный» байт-код java и виртуальную машину, Java попыталась стать языком, скомпилированным во что-то близкое к любой базовой машине, но не к реальной машине.

Современные языки объединяют все эти инновации. Некоторые имеют динамическую открытую природу традиционных интерпретируемых языков типа «ты не знаешь, что получишь до времени выполнения» (ruby, lisp, smalltalk, python, perl (!)), Некоторые пытаются иметь строгую спецификацию, позволяющую детально обнаруживать статические ошибки на основе типов в традиционных скомпилированных языках (java, scala). Все компилируются в фактические машинно-независимые представления (JVM), чтобы получить семантику однократной записи в любом месте.

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

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

3 голосов
/ 04 апреля 2009

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

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

3 голосов
/ 04 апреля 2009

Вы можете запускать программы Ruby в интерактивном режиме, используя irb , Интерактивную оболочку Ruby. Хотя он может генерировать промежуточный байт-код, он, конечно, не является «компилятором» в традиционном смысле.

0 голосов
/ 27 ноября 2011

Что касается информации, которую я получил от RubyConf 2011 в Шанхае, Matz разрабатывает MRuby (расшифровывается как Ruby от Matz) для работы на встроенных устройствах. По словам Матца, MRuby предоставит возможность компилировать код ruby ​​в машинный код, чтобы повысить скорость и уменьшить использование (ограниченных) ресурсов на встроенных устройствах. Итак, существуют различные разновидности Ruby, и определенно не все из них просто интерпретируются во время выполнения.

0 голосов
/ 04 апреля 2009

Возможно, это немного не по теме, но ...

Iron Ruby является реализацией ruby ​​на основе .net и поэтому обычно компилируется в байтовый код, а затем JIT компилируется в машинный язык во время выполнения (т.е. не интерпретируется). Также (по крайней мере, с другими языками .net, поэтому я предполагаю, что с ruby) ngen можно использовать для заблаговременной генерации скомпилированного собственного двоичного файла, так что это фактически скомпилированная машинным кодом версия кода ruby.

...