Интерпретируемые языки - использование скомпилированного языка за переводчиком
Если есть какие-либо дизайнеры языков (или просто знающие люди), мне интересно узнать о методологии создания стандартных библиотек для интерпретируемых языков. В частности, что кажется лучшим подходом? Определение стандартных функций / методов на интерпретируемом языке или выполнение обработки этих вызовов на скомпилированном языке, на котором написан переводчик?
Что заставило меня задуматься об этом, так это SO вопрос о функции, подобной stripslashes() в Python. Моей первой мыслью было "почему бы не определить свое собственное и просто вызвать его, когда вам это нужно", но возникло вопрос: предпочтительно ли для такой функции разрешить интерпретируемому языку обрабатывать эти издержки, или было бы лучше написать расширение и использовать скомпилированный язык за интерпретатором?
4 ответа
Граница между "интерпретируемыми" и "скомпилированными" языками в наши дни очень размыта. Например, первое, что делает Python, когда он видит исходный код, - это компилирует его в представление байт-кода, по сути, то же самое, что делает Java при компиляции файлов классов. Вот что содержат *.pyc файлы. Затем среда выполнения Python выполняет байт-код без обращения к исходному источнику. Традиционно, чисто интерпретируемый язык будет постоянно ссылаться на исходный код при выполнении программы.
При построении языка хорошим подходом является создание прочной основы, на которой вы можете реализовать функции более высокого уровня. Если у вас есть надежная и быстрая система обработки строк, то разработчик языка может (и должен) реализовать что-то вроде stripslashes() вне базовой среды выполнения. Это сделано по крайней мере по нескольким причинам:
- Разработчик языка может показать, что язык достаточно гибок, чтобы справиться с такой задачей.
- Разработчик языка на самом деле пишет реальный код на языке, который имеет тесты и, следовательно, показывает, что основа является прочной.
- Другие люди могут легче читать, заимствовать и даже изменять функцию более высокого уровня, не имея возможности создавать или даже понимать ядро языка.
То, что такой язык, как Python, компилируется в байт-код и выполняется, не означает, что он медленный. Нет никаких причин, по которым кто-то не мог бы написать компилятор Just-In-Time (JIT) для Python в соответствии с тем, что уже делают Java и.NET, для дальнейшего повышения производительности. Фактически IronPython компилирует Python непосредственно в байт-код.NET, который затем запускается с использованием системы.NET, включая JIT.
Чтобы ответить на ваш вопрос напрямую, единственный раз, когда разработчик языка реализует функцию на языке, стоящем за средой выполнения (например, C в случае Python), это максимизирует производительность этой функции. Вот почему такие модули, как синтаксический анализатор регулярных выражений, написаны на C, а не на собственном Python. С другой стороны, такой модуль, как getopt.py, реализован на чистом Python, потому что все это можно сделать там, и использование соответствующей библиотеки C не дает никаких преимуществ.
Существует также растущая тенденция к повторной реализации языков, которые традиционно считаются "интерпретированными" на платформе, такой как JVM или CLR, - и затем обеспечивает легкий доступ к "родному" коду для взаимодействия. Таким образом, из Jython и JRuby вы можете легко получить доступ к коду Java, а из IronPython и IronRuby вы можете легко получить доступ к.NET-коду.
В подобных случаях способность "использовать скомпилированный язык в интерпретаторе" может быть описана как основной мотиватор для новой реализации.
Смотрите раздел "Документы" на сайте www.lua.org.
Особенности реализации Lua 5.0
Lua определяет все стандартные функции в базовом (ANSI C) коде. Я считаю, что это в основном по соображениям производительности. Недавно, то есть функции 'string.*' Получили альтернативную реализацию на чистом Lua, что может оказаться жизненно важным для подпроектов, где Lua запускается поверх среды выполнения.NET или Java (где нельзя использовать код на C).
Пока вы используете переносимый API для базы скомпилированного кода, такой как стандартная библиотека ANSI C или STL в C++, использование этих функций не позволит вам заново изобретать колесо и, вероятно, обеспечит меньший, более быстрый интерпретатор. Lua использует этот подход, и он определенно небольшой и быстрый по сравнению со многими другими.