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

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

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

Меня смущает проблема компиляции / интерпретации Ruby.

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

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


person Paul Dexter    schedule 04.04.2009    source источник
comment
Для пояснения в статье SAP, на которую я ссылался, также говорилось о компиляции в байт-код. Итак, если мы принимаем байт-код ВМ как скомпилированный (что я вижу аргументы за и против), то MRI, безусловно, компилируется.   -  person Chuck    schedule 04.04.2009


Ответы (7)


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

person Keith Gaughan    schedule 04.04.2009

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

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

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

person Steven Huwig    schedule 04.04.2009
comment
Java с включенным JIT .... Разве это не должна быть Java с отключенным JIT, поскольку JIT компилирует байт-код в машинный код? Поэтому, если компилятор генерирует что-то для JITted, он не генерирует машинный код. - person stonedauwg; 31.01.2017

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

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

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

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

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

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

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

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

person marc meyer    schedule 02.06.2011

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

person tvanfosson    schedule 04.04.2009

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

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

person Jeremy Stanley    schedule 04.04.2009

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

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

person Christopher Edwards    schedule 04.04.2009

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

person Tyrael Tong    schedule 27.11.2011