Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

Метапрограммирование - это метод программирования, при котором компьютерные программы имеют возможность обрабатывать другие программы как свои данные. Это означает, что программа может быть разработана для чтения, генерации, анализа или преобразования других программ и даже для изменения самой себя во время работы. [1] [2] В некоторых случаях это позволяет программистам минимизировать количество строк кода для выражения решения, что, в свою очередь, сокращает время разработки. [3] Это также обеспечивает большую гибкость программ для эффективной обработки новых ситуаций без перекомпиляции.

Метапрограммирование может использоваться для перемещения вычислений из времени выполнения во время компиляции , для генерации кода с использованием вычислений во время компиляции и для включения самомодифицирующегося кода . Способность языка программирования быть собственным метаязыком называется рефлексией . [4] Отражение - это ценная языковая функция, облегчающая метапрограммирование.

Метапрограммирование было популярно в 1970-х и 1980-х годах с использованием языков обработки списков, таких как LISP . Аппаратные машины LISP были популярны в 1980-х годах и позволяли приложениям обрабатывать код. Они часто использовались для приложений искусственного интеллекта .

Подходы [ править ]

Метапрограммирование позволяет разработчикам писать программы и разрабатывать код, подпадающий под общую парадигму программирования . Наличие самого языка программирования как первоклассного типа данных (как в Lisp , Prolog , SNOBOL или Rebol ) также очень полезно; это известно как гомоиконность . Универсальное программирование вызывает средство метапрограммирования в языке, позволяя писать код, не заботясь об указании типов данных, поскольку они могут быть предоставлены как параметры при использовании.

Метапрограммирование обычно работает одним из трех способов. [5]

  1. Первый подход состоит в том, чтобы предоставить программному коду доступ к внутренним компонентам механизма времени выполнения через интерфейсы прикладного программирования (API), подобные тому, который используется для эмиттера .NET IL .
  2. Второй подход - это динамическое выполнение выражений, которые содержат команды программирования, часто составленные из строк, но также могут исходить из других методов, использующих аргументы или контекст, например Javascript. [6] Таким образом, «программы могут писать программы». Хотя оба подхода могут использоваться в одном языке, большинство языков склоняются к одному или другому.
  3. Третий подход - полностью выйти за пределы языка. Системы преобразования программ общего назначения , такие как компиляторы, которые принимают описания языков и выполняют произвольные преобразования на этих языках, являются прямыми реализациями общего метапрограммирования. Это позволяет применять метапрограммирование практически к любому целевому языку, независимо от того, обладает ли этот целевой язык собственными способностями к метапрограммированию. Можно увидеть это в работе со Scheme и как он позволяет преодолевать некоторые ограничения, с которыми сталкивается в C , используя конструкции, которые были частью самого языка Scheme для расширения C. [7]

Лисп , вероятно, является наиболее существенным языком со средствами метапрограммирования, как из-за его исторического приоритета, так и из-за простоты и мощности его метапрограммирования. В метапрограммировании Лиспа оператор отмены кавычек (обычно запятая) вводит код, который оценивается во время определения программы, а не во время выполнения; см. Самооценку форм и цитирование в Лиспе . Таким образом, язык метапрограммирования идентичен основному языку программирования, а существующие подпрограммы Lisp при желании могут быть напрямую повторно использованы для метапрограммирования. Этот подход был реализован на других языках путем включения в программу интерпретатора, который работает непосредственно с данными программы. Существуют реализации такого рода для некоторых распространенных языков высокого уровня, таких как RemObjects.' Сценарий Паскаля для Object Pascal .

Использование [ править ]

Генерация кода [ править ]

Простым примером метапрограммы является сценарий POSIX Shell , который является примером генеративного программирования :

#! / bin / sh # метапрограмма echo  '#! / bin / sh' > программа для i в  $ ( seq 992 ) do  echo  "echo $ i " >> программа выполненапрограмма chmod + x

Этот сценарий (или программа) генерирует новую программу из 993 строк, которая выводит числа 1–992. Это только иллюстрация того, как использовать код для написания большего количества кода; это не самый эффективный способ распечатать список чисел. Тем не менее, программист может написать и выполнить эту метапрограмму менее чем за минуту и ​​за это время сгенерирует более 1000 строк кода.

Куайн это особый вид метапрограммы , который производит свой собственный исходный код своей продукции. Квайн обычно представляет только развлекательный или теоретический интерес.

Не все метапрограммирование включает в себя генеративное программирование. Если программы можно изменять во время выполнения или доступна инкрементная компиляция (например, в C # , Forth , Frink , Groovy , JavaScript , Lisp , Elixir , Lua , Perl , PHP , Python , REBOL , Ruby , Rust , SAS , Smalltalk и Tcl ), то можно использовать методы для выполнения метапрограммирования без фактического создания исходного кода.

Один из стилей генеративного подхода - использование предметно-ориентированных языков (DSL). Достаточно распространенный пример использования DSL включает в себя генеративное метапрограммирование: lex и yacc , два инструмента, используемых для создания лексических анализаторов и синтаксических анализаторов , позволяющих пользователю описывать язык с помощью регулярных выражений и контекстно-свободных грамматик и встраивать сложные алгоритмы, необходимые для эффективного анализа язык.

Инструментарий кода [ править ]

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

Поведенческие изменения [ править ]

Метапрограммирование может использоваться для внесения поведенческих изменений в программу, как это делается в аспектно-ориентированном программировании . Например, метапрограммирование может использоваться для внедрения флагов функций или для изучения возможных патчей для исправления ошибок. [8]

Проблемы [ править ]

Некоторые утверждают, что для полноценного использования функций метапрограммирования требуется резкая кривая обучения. [9] Поскольку метапрограммирование дает большую гибкость и настраиваемость во время выполнения, неправильное или неправильное использование метапрограммирования может привести к неоправданным и неожиданным ошибкам, отладку которых может быть чрезвычайно сложно для среднего разработчика. Он может внести риски в систему и сделать ее более уязвимой, если не использовать ее с осторожностью. Некоторые из распространенных проблем, которые могут возникнуть из-за неправильного использования метапрограммирования, - это неспособность компилятора идентифицировать отсутствующие параметры конфигурации, недопустимые или неверные данные могут привести к неизвестному исключению или другим результатам. [10] Некоторые считают, что [9] что только высококвалифицированные разработчики должны работать над разработкой функций, которые осуществляют метапрограммирование на языке или платформе, а средние разработчики должны научиться использовать эти функции в рамках соглашения.

Используется в языках программирования [ править ]

Макросистемы [ править ]

  • Общий Лисп и большинство диалектов Лиспа .
  • Схема гигиенического макроса
  • MacroML
  • Ракетка (язык программирования)
  • Шаблон Haskell
  • Scala макросы
  • Clojure макросы
  • Ним
  • Ржавчина
  • Haxe
  • Юлия

Макроассемблеры [ править ]

IBM / 360 и производные были мощные макроассемблера объектов , которые часто используются для создания полных ассемблера программ [ источник ? ] Или разделов программ (для различных операционных систем, например). Макросы, поставляемые с системой обработки транзакций CICS, содержат макросы ассемблера, которые генерируют операторы COBOL на этапе предварительной обработки.

Другие ассемблеры, такие как MASM , также поддерживают макросы.

Метаклассы [ править ]

Метаклассы предоставляются следующими языками программирования:

  • Общий Лисп [11]
  • Python
  • Ноль
  • Groovy
  • Рубин
  • Болтовня
  • Lua

Метапрограммирование шаблона [ править ]

  • C «X Macros»
  • Шаблоны C ++
  • D
  • Common Lisp , Scheme и большинство диалектов Lisp с использованием оператора квазицитата ("обратная кавычка"). [12]
  • Ним

Поэтапное метапрограммирование [ править ]

  • MetaML
  • MetaOCaml
  • Scala с использованием Lightweight Modular Staging Framework [13] [14]
  • Terra

Зависимые типы [ править ]

Использование зависимых типов позволяет доказать, что сгенерированный код никогда не является недействительным. [15] Однако этот подход является передовым и редко встречается за пределами исследовательских языков программирования.

Реализации [ править ]

Список известных систем метапрограммирования поддерживается в Списке систем преобразования программ .

См. Также [ править ]

  • Аспект ткачиха
  • Сравнение инструментов генерации кода
  • Отражение во время компиляции
  • Генетическое программирование
  • Гомоиконность
  • Логическое программирование
  • Симулятор набора инструкций
  • Преднамеренное программирование
  • Интерпретируемый язык
  • Машинное обучение
  • Метакомпилятор
  • Метаобъект
  • Частичная оценка
  • Отражение (компьютерное программирование)
  • Самостоятельный переводчик
  • Самомодифицирующийся код
  • Генерация исходного кода
  • Транскомпилятор (также известный как транспиляция)
  • Очень крупномасштабная интеграция

Ссылки [ править ]

  1. ^ Харальд Сондергаард. «Курс анализа и трансформации программ» . Проверено 18 сентября 2014 года .
  2. ^ Чарнецкий, Кшиштоф ; Эйзенекер, Ульрих В. (2000). Генеративное программирование . ISBN 0-201-30977-7.
  3. ^ Уокер, Макс. «Искусство метапрограммирования на Java» . Новый круг . Проверено 28 января 2014 .
  4. ^ Краусс, Аарон. "Концепции программирования: самоанализ и размышление о типах" . Общество . Проверено 14 сентября 2014 года .
  5. Джоши, Пратик. «Что такое метапрограммирование? - Часть 2/2» . Вечная загадка . Проверено 14 августа 2014 года .
  6. ^ например, instance_eval в Ruby принимает строку или анонимную функцию. «Rdoc для класса: BasicObject (Ruby 1.9.3) - instance_eval» . Проверено 30 декабря 2011 года .
  7. ^ «Искусство метапрограммирования» .
  8. ^ Дюрье, Томас; Корню, Бенуа; Сейнтюрье, Лайонел; Монперрус, Мартин (2017). «Динамическое создание исправлений для исключений с нулевым указателем с использованием метапрограммирования» (PDF) . 24-я Международная конференция по анализу, эволюции и реинжинирингу программного обеспечения, IEEE, 2017 (SANER) . IEEE: 349–358. DOI : 10,1109 / SANER.2017.7884635 . ISBN  978-1-5090-5501-2.
  9. ^ a b Bicking, Ян. «Проблема метапрограммирования» . IanBicking.org . Проверено 21 сентября 2016 года .
  10. ^ Терри, Мэтт. «Остерегайтесь метапрограммирования» . Medium.com . Средняя корпорация . Проверено 21 августа 2014 .
  11. ^ Через"Протоколметаобъектов Common Lisp Object "
  12. ^ Lisp (язык программирования) «Самооценка форм и цитирование», оператор квази-кавычек.
  13. ^ «LMS: создание программ и встроенные компиляторы в Scala» . scala-lms.github.io . Проверено 6 декабря 2017 .
  14. ^ Ромпф, Тиарк; Одерский, Мартин (июнь 2012). «Облегченная модульная постановка: прагматический подход к генерации кода времени выполнения и скомпилированным DSL» . Commun. ACM . 55 (6): 121–130. DOI : 10.1145 / 2184319.2184345 . ISSN 0001-0782 . 
  15. ^ Chlipala, Адам (июнь 2010). «Ur: статически типизированное метапрограммирование с вычислением записей на уровне типа» (PDF) . Уведомления ACM SIGPLAN . PLDI '10. 45 (6): 122–133. DOI : 10.1145 / 1809028.1806612 . Проверено 29 августа 2012 года .

Внешние ссылки [ править ]

  • c2.com Wiki: статья о метапрограммировании
  • Мета-программирование в вики по преобразованию программ
  • Генерация кода против метапрограммирования
  • "Соленоид" : первый фреймворк для метапрограммирования для eXist-db.