Metaprogramming
![]() | В этой статье есть несколько проблем. Пожалуйста, помогите улучшить его или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалять эти шаблонные сообщения )
|
Метапрограммирование — это метод компьютерного программирования , при котором компьютерные программы имеют возможность обращаться с другими программами как со своими данными . Это означает, что программа может быть спроектирована так, чтобы читать, генерировать, анализировать или преобразовывать другие программы и даже изменять себя во время работы. [1] [2] В некоторых случаях это позволяет программистам минимизировать количество строк кода для выражения решения, что, в свою очередь, сокращает время разработки. [3] Это также позволяет программам более гибко справляться с новыми ситуациями без перекомпиляции.
Метапрограммирование можно использовать для перемещения вычислений из среды выполнения во время компиляции , для генерации кода с использованием вычислений во время компиляции и для включения самомодифицирующегося кода . Способность языка программирования быть собственным метаязыком делает возможным рефлексивное программирование , и это называется отражением . [4] Рефлексия — ценная функция языка, облегчающая метапрограммирование.
Метапрограммирование было популярно в 1970-х и 1980-х годах с использованием языков обработки списков, таких как Lisp . Машинное оборудование Lisp приобрело известность в 1980-х годах и позволило использовать приложения, способные обрабатывать код. Их часто использовали для приложений искусственного интеллекта .
Подходы [ править ]
Метапрограммирование позволяет разработчикам писать программы и разрабатывать код, который подпадает под программирования общую парадигму . Наличие самого языка программирования как первоклассного типа данных (как в Lisp , Prolog , SNOBOL или Rebol ) также очень полезно; это известно как гомоиконичность . Общее программирование задействует средства метапрограммирования внутри языка, позволяя писать код, не заботясь об указании типов данных, поскольку они могут быть предоставлены в качестве параметров при использовании .
Метапрограммирование обычно работает одним из трех способов. [5]
- Первый подход заключается в том, чтобы предоставить доступ внутренних компонентов системы времени выполнения к программному коду (движка) через интерфейсы прикладного программирования (API), подобные тому, что используется в эмиттере .NET Common Intermediate Language (CIL).
- Второй подход — динамическое выполнение выражений, которые содержат команды программирования, часто состоящие из строк, но также могут быть получены из других методов с использованием аргументов или контекста, например JavaScript . [6] Таким образом, «программы могут писать программы». Хотя оба подхода могут использоваться в одном и том же языке, большинство языков склоняются к одному или другому.
- Третий подход — полностью выйти за пределы языка. общего назначения Системы преобразования программ , такие как компиляторы , которые принимают описания языков и выполняют произвольные преобразования на этих языках, являются прямыми реализациями общего метапрограммирования. Это позволяет применять метапрограммирование практически к любому целевому языку независимо от того, обладает ли этот целевой язык какими-либо собственными способностями метапрограммирования. Можно увидеть это в работе со Scheme и то, как она позволяет преодолеть некоторые ограничения, с которыми сталкивается C , используя конструкции, являющиеся частью языка Scheme, для расширения C. [7]
Лисп, вероятно, является наиболее существенным языком с возможностями метапрограммирования, как из-за его исторического преобладания, так и из-за простоты и мощи его метапрограммирования. В метапрограммировании на Лиспе оператор отмены кавычек (обычно запятая) вводит код, который оценивается во время определения программы, а не во время ее выполнения. Таким образом, язык метапрограммирования идентичен основному языку программирования, и существующие процедуры Lisp при желании могут быть напрямую повторно использованы для метапрограммирования. Этот подход был реализован на других языках путем включения в программу интерпретатора, который работает непосредственно с данными программы. Существуют реализации такого рода для некоторых распространенных языков высокого уровня, таких как для RemObjects Pascal Script Object Pascal .
Использование [ править ]
Генерация кода [ править ]
Простым примером метапрограммы является этот POSIX Shell сценарий , который является примером генеративного программирования :
#!/bin/sh# metaprogramecho '#!/bin/sh' > programfor i in $(seq 992)do echo "echo $i" >> programdonechmod +x program
Этот сценарий (или программа) генерирует новую программу из 993 строк, которая печатает числа от 1 до 992. Это всего лишь иллюстрация того, как использовать код для написания большего количества кода; это не самый эффективный способ распечатать список чисел. Тем не менее, программист может написать и выполнить эту метапрограмму менее чем за минуту и за это время сгенерирует более 1000 строк кода.
Куайн — это особый вид метапрограммы , которая на выходе создает собственный исходный код. Куайны обычно представляют только развлекательный или теоретический интерес.
Не все метапрограммирование включает в себя генеративное программирование. Если программы можно модифицировать во время выполнения или доступна инкрементная компиляция (например, в C# , Forth , Frink , Groovy , JavaScript , Lisp , Elixir , Lua , Nim , Perl , PHP , Python , Rebol , Ruby , Rust , R , SAS) , Smalltalk и Tcl ), то можно использовать методы метапрограммирования без генерации исходного кода.
Одним из стилей генеративного подхода является использование предметно-ориентированных языков (DSL). Довольно распространенный пример использования DSL включает генеративное метапрограммирование: lex и yacc , два инструмента, используемых для создания лексических анализаторов и синтаксических анализаторов , позволяют пользователю описывать язык с помощью регулярных выражений и контекстно-свободных грамматик , а также внедрять сложные алгоритмы, необходимые для эффективного анализа язык.
Инструментирование кода [ править ]
Одним из применений метапрограммирования является инструментирование программ для проведения динамического анализа программ .
Проблемы [ править ]
Некоторые утверждают, что для того, чтобы в полной мере использовать возможности метапрограммирования, необходимо резкое обучение. [8] Поскольку метапрограммирование обеспечивает большую гибкость и возможность настройки во время выполнения, неправильное использование или неправильное использование метапрограммирования может привести к необоснованным и неожиданным ошибкам, отладка которых обычному разработчику может быть чрезвычайно трудной. Это может привести к возникновению рисков в системе и сделать ее более уязвимой, если не использовать ее с осторожностью. Некоторые из распространенных проблем, которые могут возникнуть из-за неправильного использования метапрограммирования, - это неспособность компилятора определить недостающие параметры конфигурации, неверные или неправильные данные могут привести к неизвестному исключению или другим результатам. [9] В связи с этим некоторые считают [8] что только высококвалифицированные разработчики должны работать над разработкой функций, реализующих метапрограммирование на языке или платформе, а средние разработчики должны научиться использовать эти функции в рамках соглашения.
Использование в языках программирования [ править ]
Макросистемы [ править ]
Макросемблеры [ править ]
IBM /360 и его производные имели мощные средства ассемблера макросов , которые часто использовались для создания полных на языке ассемблера . программ [ нужна ссылка ] или разделы программ (например, для разных операционных систем). Макросы, поставляемые с CICS, системой обработки транзакций имели макросы ассемблера, которые генерировали инструкции COBOL в качестве этапа предварительной обработки.
Другие ассемблеры, такие как MASM , также поддерживают макросы.
Метаклассы [ править ]
Метаклассы предоставляются следующими языками программирования:
Template metaprogramming [ edit ]
- C "X Макросы"
- Шаблоны С++ [11]
- Д
- Common Lisp , Scheme и большинство диалектов Lisp с использованием оператора квазикавычки («обратная кавычка»). [12]
- Nim
Staged metaprogramming [ edit ]
- МетаМЛ
- МетаОКамл
- Scala изначально или с использованием облегченной модульной промежуточной платформы. [13] [14]
- Земля
Зависимые типы [ править ]
Использование зависимых типов позволяет доказать, что сгенерированный код никогда не является невалидным. [15] Однако этот подход является передовым и редко встречается за пределами исследовательских языков программирования.
Реализации [ править ]
Список известных систем метапрограммирования поддерживается в списке систем преобразования программ .
См. также [ править ]
- Аспект ткача
- Сравнение инструментов генерации кода
- Выполнение функции во время компиляции
- Генетическое программирование
- Гомоконичность
- Инференциальное программирование
- Симулятор набора команд
- Намеренное программирование
- Интерпретируемый язык
- Машинное обучение
- Метакомпилятор
- Метаобъект
- Частичная оценка
- Рефлексивное программирование , а также отражение времени компиляции
- Самопереводчик
- Самомодифицирующийся код
- Генерация исходного кода
- Транскомпилятор (также известный как транспиляция)
- Очень масштабная интеграция
- Проблема с остановкой
Ссылки [ править ]
- ^ Зондергаард, Харальд (2013). «Курс программного анализа и трансформации» . Проверено 18 сентября 2014 г.
- ^ Чарнецкий, Кшиштоф ; Эйзенекер, Ульрих В. (2000). Генеративное программирование . ISBN 0-201-30977-7 .
- ^ Уокер, Макс. «Искусство метапрограммирования на Java» . Новый круг . Проверено 28 января 2014 г.
- ^ Краусс, Аарон. «Концепции программирования: самоанализ и рефлексия типов» . Общество . Проверено 14 сентября 2014 г.
- ^ Джоши, Пратик (5 апреля 2014 г.). «Что такое метапрограммирование? – Часть 2/2» . Вечная загадка . Проверено 14 августа 2014 г.
- ^ например, example_eval в Ruby принимает строку или анонимную функцию. «Rdoc для класса: BasicObject (Ruby 1.9.3) — instance_eval» . Проверено 30 декабря 2011 г.
- ^ «Искусство метапрограммирования» . ИБМ .
- ↑ Перейти обратно: Перейти обратно: а б Бикинг, Ян. «Задача метапрограммирования» . IanBicking.org . Проверено 21 сентября 2016 г.
- ^ Терри, Мэтт (21 августа 2013 г.). «Остерегайтесь метапрограммирования» . Medium.com . Средняя корпорация . Проверено 21 августа 2014 г.
- ^ Через Common Lisp Object System . «Протокол метаобъектов»
- ^ «Метапрограммирование шаблонов C++» . aszt.inf.elte.hu. Проверено 23 июля 2022 г.
- ^ Lisp (язык программирования) «Самовычисляемые формы и кавычки», оператор квазикавычек.
- ^ «LMS: генерация программ и встроенные компиляторы в Scala» . scala-lms.github.io . Проверено 6 декабря 2017 г.
- ^ Ромпф, Тиарк; Одерский, Мартин (июнь 2012 г.). «Облегченная модульная промежуточная подготовка: прагматичный подход к генерации кода во время выполнения и скомпилированным DSL» . Коммуникации АКМ . 55 (6): 121–130. дои : 10.1145/2184319.2184345 . ISSN 0001-0782 . S2CID 52898203 .
- ^ Члипала, Адам (июнь 2010 г.). «Ур: статически типизированное метапрограммирование с вычислением записей на уровне типа» (PDF) . Уведомления ACM SIGPLAN . ПЛДИ '10. 45 (6): 122–133. дои : 10.1145/1809028.1806612 . Проверено 29 августа 2012 г.
Внешние ссылки [ править ]
- c2.com Wiki: Metaprogramming article
- Метапрограммирование на Wiki Program Transformation
- Code generation Vs Metaprogramming
- «Solenoid» : первая среда метапрограммирования для eXist-db.