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