Метапрограммирование
Метапрограммирование — вид программирования, связанный с созданием программ, которые порождают другие программы как результат своей работы[1] (в частности, на стадии компиляции их исходного кода), либо программ, которые меняют себя во время выполнения (самомодифицирующийся код). Первое позволяет получать программы при меньших затратах времени и усилий на кодирование, чем если бы программист писал их вручную целиком, второе позволяет улучшить свойства кода (размер и быстродействие).
Генерация кода
При этом подходе код программы не пишется вручную, а создаётся автоматически программой-генератором на основе другой программы.
Такой подход приобретает смысл, если при программировании вырабатываются различные дополнительные правила (более высокоуровневые парадигмы, выполнение требований внешних библиотек, стереотипные методы реализации определённых функций и пр.). При этом часть кода (или данных) теряет содержательный смысл и становится лишь механическим выполнением правил. Когда эта часть становится значительной, возникает мысль задавать вручную лишь содержательную часть, а остальное добавлять автоматически. Это и проделывает генератор.
Различаются два принципиально различных вида кодогенерации:
- генератор является физически отдельной бинарной программой, необязательно написанной на целевом языке.
- целевой язык является одновременно языком реализации генератора, так что метапрограмма составляет с целевой программой единое целое.
Наиболее распространённым и наглядным примером первого случая являются GUI построители, где метапрограмма нацелена на пользовательское программирование, позволяя несведущим в программировании специалистам в области эргономики принимать непосредственное участие в разработке программных продуктов. В этом случае метапрограмма оказывается заведомо намного более сложной, крупной и трудоёмкой в разработке, чем порождаемый ею код, и её разработка оправдывается частотой её использования. Следует отметить, что на практике, как правило (но не обязательно), такого рода метапрограммы пишутся на императивных языках для использования в императивных же языках, и поставляются в скомпилированном виде. Недостатком этого метода является невозможность повторного использования кода метапрограммы при разработке новых, более сложных метапрограмм.
Другим примером являются генераторы синтаксических и лексических анализаторов, такие как Lex, YACC, ANTLR, bison.
Второй случай представляет собой встраивание языка и реализуется тремя статическими методами c использованием макросредств языка или чистым встраиванием. В этом случае наработки, накопленные в процессе разработки метапрограмм, в дальнейшем могут интенсивно повторно использоваться для разработки новых метапрограмм[2].
Другие примеры:
- В Perl существует понятие «source filters» («фильтров исходного кода») — метода переработки файлов с исходным кодом перед выполнением, позволяющего полностью менять синтаксис и семантику языка. Одним из известных примеров является модуль Lingua::Romana::Perligata, позволяющий писать код Perl на латыни.[3]
- В Форт программисту предоставляют встроенные в язык возможности по изменению своего синтаксиса и семантики. Это достигается определением архитектуры виртуальной машины и полным доступом к возможностям изменения её составляющих.
Самомодифицирующийся код
Возможность изменять или дополнять себя во время выполнения превращает программу в виртуальную машину. Хотя такая возможность существовала уже давно на уровне машинных кодов (и активно использовалась, например, при создании полиморфных вирусов), с метапрограммированием обычно связывают перенос подобных технологий в высокоуровневые языки.
Основные методы реализации:
- Гомоиконность — инструкции по самоидентификации или изменению кода основываются на том же синтаксисе, что и сам код.
- Интроспекция — представление внутренних структур языка в виде переменных встроенных типов с возможностью доступа к ним из программы (в терминах С++ это будет соответствовать технологиям динамического полиморфизма и динамического приведения типов).
- Позволяет во время выполнения просматривать, создавать и изменять определения типов, стек вызовов, обращаться к переменной по имени, получаемому динамически и пр.
- Пространство имён
System.Reflection
и типSystem.Type
в .NET; классыClass, Method, Field
в Java; представление пространств имен и определений типов через встроенные типы данных в Python; стандартные встроенные возможности в Форт по доступу к ресурсам виртуальной машины; получение значения и изменение свойств почти любого из объектов в ECMAScript (с оговорками).
- Пространство имён
- Интерпретация произвольного кода, представленного в виде строки.
- Существует естественным образом во множестве интерпретируемых языков (впервые функция
eval
была реализована в Lisp, а точнее, непосредственно перед ним, ставшим её первым реализованным интерпретатором). - Компилятор Tiny C позволяет «на лету» компилировать и исполнять код на языке C, представленный в виде строки символов.
- Для Форт использования процедуры интерпретации из строки EVALUATE.
- Существует естественным образом во множестве интерпретируемых языков (впервые функция
В языке Пролог метапрограммирование позволяет автоматизировать разработку и верификацию (проверку свойств) Пролог-программ. Метапрограммы рассматривают программы на Прологе как термы и позволяют анализировать их свойства и взаимоотношения, строить программы для управления другими Пролог-программами[4].
См. также
Примечания
- Джонатан Бартлетт, Искусство метапрограммирования, Часть 1: Введение в метапрограммирование
- Paul Hudak. Modular Domain Specific Languages and Tools. — IEEE Computer Society Press, Department of Computer Science, Yale University, 1998. Архивировано 17 октября 2013 года.
- Lingua::Romana::Perligata — search.cpan.org
- Metakides, G. and Nerode, A. (1998): Principles of logic and logic programming (translation in Romanian). Tehnical Publishing House, Bucharest.
Ссылки
- R# — метапрограммирование в .Net
- BOOST MPL LIBRARY (англ.) — библиотека для метапрограммирования с использованием шаблонов C++
- Boost Preprocessor Library (англ.) — библиотека для метапрограммирования с использованием препроцессора C++
- Статья об ещё одном подходе к метапрограммированию (англ.)
- Клаус Крэфт, Анжелика Лангер. Шаблоны выражений (expression templates). Часть 1 Часть 2
- Джонатан Бартлетт, Искусство метапрограммирования, Часть 1: Введение в метапрограммирование