Какое использование метапрограммирования?

Я читал:

и я исповедую некоторую путаницу с целью метапрограммирования/генерации кода.

Есть ли у кого-нибудь конкретный пример того, где они используют метапрограммирование/генерацию кода? Еще лучше было бы сопроводительное объяснение того, почему это было лучше, чем альтернатива.

изменить: Можно ли считать Thistle метапрограммированием?

Ответ 1

Представьте себе парня, который строит автомобили. Скажите это так же, как с помощью компьютера.
В какой-то момент он понимает, что он всегда делает то же самое, более или менее.
Поэтому он строит заводы для производства автомобилей, и это намного лучше. Он сейчас программирует!
Тем не менее, еще раз, в какой-то момент он понимает, что он всегда делает то же самое, в какой-то степени.
Теперь он решает построить заводы, которые строят заводы, которые строят автомобили. Это метапрограммирование.

Метапрограммирование очень мощно, но один сбой в системе делает все преимущества превращены в трудности монстров. Итак, овладейте им и используйте его... Или держитесь подальше!

Ответ 2

Я думаю о метапрограммировании как "программах, которые пишут (или изменяют) другие программы". (Еще один ответ сказал "фабрики, которые производят фабрики", хорошая аналогия).

Люди находят все виды использования для этого: настраивая приложения, генерируя шаблонный код, оптимизация программы для особых обстоятельств, внедрение DSL, вставка кода для обработки проблемы с ортогональным дизайном ( "аспекты" )...

Что примечательно, сколько разных механизмов было изобретено для этого по частям: текстовые шаблоны, макросы, условные препроцессоры, дженерики, С++ - шаблоны, аспекты, отражение,... И обычно некоторые из этих механизмов встроены в некоторые языки и другие механизмы на другие языки, и большинство языков вообще не поддерживают метапрограммирование. Это распределение возможностей с разбросом кадров означает, что вы можете сделать некоторые виды метапрограммирования на одном языке, с ограничениями и, тем не менее, не в состоянии делать эти виды в другом. Это усугубляет: -}

Наблюдение, которое я следил за рукояткой, заключается в том, что можно построить общий метапрограммирующее устройство, которое работает на любом языке в форме программные преобразования. Преобразование программы - это параметризованный шаблон: "если вы видите этот синтаксис, замените его на этот синтаксис".

Одна трансформация сама по себе вообще не впечатляет, но десятки или сотни могут сделать впечатляющие изменения в коде. Потому что (сложные) преобразования программы могут в эффект имитирует машину Тьюринга, они могут выполнять произвольные изменения кода, в том числе все эти точечные методы, которые вы обнаружите, разбросаны.

Инструмент, который принимает определения языка. языковые преобразования и генерирует другой для применения этих преобразований - это мета-метапрограммирование: программа для записи "программ, которые пишут программы".

Значение заключается в том, что вы можете применить такой инструмент для выполнения широких разновидностей изменений к произвольному коду. И вам не нужен комитет по разработке языка, чтобы понять, что вы хотите получить определенную поддержку метапрограммирования и поторопитесь предоставить ее так что вы можете продолжить свою работу сегодня.

Интересным уроком является то, что такой механизм нуждается в сильном анализе программ (символ таблицы, контроль и анализ потока данных и т.д.) поддержку, чтобы помочь ему сосредоточиться на проблемах в коде, чтобы метапрограммирование машины могут что-то сделать в этот момент (очень слабый пример этого точечные спецификации в аспектах, которые говорят "вносить изменения в места, которые выглядят так" ).

ОП запросил конкретные примеры использования метапрограммирования. Мы использовали наш инструмент meta-metaprogramming (DMS Software Reengineering Toolkit), чтобы автоматически выполнять следующие действия на больших кодовых основаниях:

  • Языковая миграция
  • Реализация тестового покрытия и профилировщиков
  • Реализация обнаружения клонов
  • Реинжиниринг массивной архитектуры
  • Генерация кода для управления factory
  • SOAization встроенных сетевых контроллеров
  • Извлечение архитектуры для программного обеспечения для мэйнфреймов
  • Генерация векторных команд SIMD из вычислений массивов
  • Обратное проектирование кода обратно к концепциям

на многих языках, включая Java, С#, С++, PHP,...

ОП также спросил: "Почему это было лучше, чем альтернатива?" Ответ должен соответствовать масштабам, времени и точности.

Для больших приложений чистый размер базы кода означает, что у вас нет ресурсов или время проведения таких анализов или изменений вручную.

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

В сущности, эти инструменты делают то, что люди просто не могут.

Стоит отметить, что инструменты не имеют творчества; ты все еще нужно, чтобы люди определяли, что им делать, например, решать какова задача (см. пример выше) и определить как определить анализы/преобразования для достижения эффекта. Вам все еще нужны метапрограммы. Однако, когда метапрограммист вооружение такого инструмента с правильными знаниями, полученный код может по-видимому, построены невероятно быстрым, креативным, экспертным кодером.

Ответ 3

Я использовал большую часть метапрограммирования для соединения между различными API-интерфейсами.

Рабочим примером будет FireBreaths JSAPIAuto 1 что облегчает запись классов С++, подверженных JavaScript. Предоставляя средство регистрации для функций, которые должны быть открыты, типы аргументов могут быть проверены и из этого кода подстановки, сгенерированного во время компиляции, который преобразуется из типов script -API-типов в родные типы С++ и обратно, даже напрямую поддерживая map, vector и т.д.

В качестве простого примера рассмотрим открытую функцию add(a, b), которая использует некоторые типы API-интерфейсов сценариев:

ScriptVariant add(const std::vector<ScriptVariant>& values) {
    // have to check argument count
    if(values.size() != 2)
        throw script_error("wrong number of arguments");

    try {
        // have to convert from scripting-API types
        long a = values[0].convert_cast<long>();
        long b = values[0].convert_cast<long>();
        return a+b; // potentially need to convert back too
    } catch(ScriptVariant::bad_cast& e) {
        // need to handle conversion failure
        throw script_error("conversion failed :(");
    }
}

Фактическая логика, зарытая в ней, есть только одна строка, проверка и конверсия которой раздражают и избыточны. С ранее упомянутой регистрационной установкой (например, в конструкторе):

registerMethod("add", make_method(this, &MyClass::add));

теперь это можно просто написать как:

long add(long a, long b) {
    return a+b;
}

... и структура заботится о создании необходимого вам кода.

1: Хотя я бы сделал реализацию немного... чище... если бы мне пришлось снова начать

Ответ 4

Мои последние (последние 6 месяцев) конкретные примеры генерации кода:

  • У меня есть SQL Plus script, который генерирует и выполняет другие скрипты SQL Plus. Генерация script запускает запросы к некоторым таблицам, которые имеют поля метки времени, а когда я создал script, было невозможно узнать, какое временное окно выбрать. Итак, главная script выполняет свою работу и выясняет, какие диапазоны времени должны быть в суб-скриптах. Затем он генерирует индексы, записывая свой код в файл (и заменяя заполнители для фактического времени начала и окончания). Наконец, он выполняет индекс (ы). Я использовал этот трюк для нескольких ситуаций (хотя часто это сложнее, чем этот), где структура подшагов зависит от результатов предыдущих шагов.

  • У меня когда-то были элементы отображения таблиц из столбцов XSD в таблицу в базе данных. Можно было генерировать XSL-фрагменты и полные запросы из электронной таблицы с использованием макросов и VBA. Эти фрагменты и запросы были скопированы и вставлены (в основном, как и без каких-либо изменений) в систему, которая их выполнила и обработала результаты. Не очень приятное решение, но, конечно же, очень утомительная работа была намного менее утомительной, и полученный код был, вероятно, гораздо более последовательным, чем если бы я потратил неделю или две, написав все это вручную.

    /li >

SO список примеров метапрограммирования: Каковы самые крутые примеры метапрограммирования, которые вы видели на С++?

Ответ 5

Я могу привести свой собственный конкретный пример: я разрабатываю ABSE, что является метапрограммным подходом. С ABSE вы создаете модель (фактически, дерево), где каждый элемент является "Atom". Этот Atom представляет собой "концепцию" и содержит необходимые метаданные для его определения.

В ABSE реализация концепции на самом деле является "мини-программой".

Затем ведущий модельер (AtomWeaver, разработанный вместе с ABSE) берет модель и "переплетает" генераторную программу из всех его Атомы. Затем эта программа запускается, генерируя нужные артефакты (исходный код, данные и т.д.).

Итак, рабочий процесс ABSE:

  • Создайте дискретную концепцию (часть мета-метапрограммы)
  • Повторное использование этой концепции в модели (эффективное построение метапрограммы)
  • Ведущий модератор переплетает и запускает метапрограмму
  • Метапрограмма генерирует вашу окончательную программу

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

Преимущества метапрограммирования (не исключительно для ABSE)?

  • Изменение модели и регенерация полной системы (Представьте себе функции рефакторинга вместо исходных строк).
  • Изменение нескольких определений в модели может привести к отдельным программам (Семейство программных продуктов).
  • При повторном использовании шаблонов вы можете изменить код шаблона, восстановить его и изменить свой код на десятки, сотни мест.
  • Многие другие, действительно

Метапрограммирование, генерация кода, трансформация программы - новые захватывающие миры в разработке программного обеспечения, ИМХО. Однако для метапрограммирования требуется новое умение: мета-мышление.

Мы можем определить мета-мышление как "размышление о том, как вы думаете о своем собственном развитии". Это своего рода классовая рефлексия, применяемая к себе. На практике вы должны узнать свои собственные шаблоны разработки, изолировать их, сделать их обобщенными, а затем превратить их в метапрограммы, используя ваш любимый метод, будучи ABSE, DSL, DSM и т.д.

Ответ 6

Библиотеки на основе метапрограммирования/помощь кода создают прямой и простой код, который будет генерировать код детали реализации для вас, в зависимости от используемых параметров.

Boost заполнен библиотеками (С++), которые демонстрируют, что может быть достигнуто с помощью метапрограммирования. Некоторые хорошие (и, возможно, трудно понять) примеры: Proto, которые позволяют реализовать DSL, Spirit, которые позволяют писать компилятор с помощью EBNF непосредственно внутри кода и многих других духовых библиотек.

Ответ 7

Я попытаюсь объяснить мой конкретный пример использования методов метапрограммирования.

Я создал программный инструмент, который будет генерировать исходный код веб-страницы ASP.NET из любой формы ввода данных MS Access. Техника, которую я использовал, заключалась в создании собственных текстовых шаблонов ASP.NET для каждого типа элемента управления формы. Я просто подключил такие значения, как TOP, LEFT, HEIGHT, WIDTH, CONTROLSOURCE из метаданных объектов формы MS Access. Например, мой шаблон для текстового поля ASP.NET выглядит так:

 <asp:TextBox ID="**ID**" runat="server" style="z-index: 1; left: **LL**px; top: **TOP**px; position: absolute"  Text='<%# Bind("[**CTLSOURCE**]") %>' />

после получения значений метаданных элемента управления textbox моя программа генерирует код для текстового поля

<asp:TextBox ID="txtCustomerID" runat="server" style="z-index: 1; left: 50px; top: 240px; position: absolute"  Text='<%# Bind("[CustomerID]") %>' />

Моя программа генерирует весь исходный код веб-страницы для одной формы MS Access за 2-3 секунды. Альтернативой является ручное кодирование веб-страницы ASP.NET с нуля; задача, которая может занять несколько часов или даже дней.

Представьте себе базу данных MS Access с 24-35 формами. Передача кода каждой формы в виде исходного кода веб-страницы ASP.NET может занять недели, если не месяцы. Использование инструмента преобразования с методами метапрограммирования в этом случае сокращает время разработки веб-страниц с недель и месяцев до часов.

Ответ 8

Конкретный пример того, где это может быть полезным подходом.

У вас есть набор сторонних классов, к которым вы хотите добавить общее поведение - например, какой-то контроль безопасности/доступа, отображение объектов как JSON и т.д.

Вы можете писать или генерировать подклассы для всего, добавляя методы-обертки для добавления в элемент управления доступом и вызывать суперкласс. При метапрограммировании вы можете это сделать во время выполнения, а также ваши изменения будут автоматически применены к любым дополнительным/измененным сторонним классам.

В примере с JSON, используя интроспекцию класса, вы должны иметь возможность генерировать код для сериализации объекта, а затем добавлять это как метод к классу. Другие экстремумы будут генерировать или писать код upfront (перед компиляцией) и влиять каждый раз, когда класс изменяется, или полностью общий подход, который использовал интроспекцию для каждого отдельного объекта, каждый раз, когда вы хотели отобразить его.

В зависимости от языка и времени выполнения, метод метапрограммирования, вероятно, будет быстрее, чем полностью общий/интроспективный, но медленнее, чем предыдущий код, поскольку вы уменьшили количество поиска данных в коде.

Если метапрограммирование не существует непосредственно на языке, мне также кажется, что он часто повторно изобретается через фреймворки (например, контейнеры стиля IoC, такие как Spring).

Ответ 9

Запустите свою Visual Studio (Eclipse, Netbeans, что-нибудь еще). Создайте новый проект. Сюрприз - вы только что использовали метапрограммирование, создав проект из шаблона. Разве это не практично?

Ответ 10

Вы можете посмотреть общие макросы Lisp или шаблоны С++ и посмотреть, как они используются. Оба метапрограммируются в том смысле, в котором вы используете. Вы обнаружите, что оба используются в большом количестве кода.

Макросы

Lisp часто используются для переопределения языка. Например, последняя глава Paul Graham В Lisp создает рабочее объектно-ориентированное расширение для Common Lisp. Другим примером является теперь несуществующий Garnet.

Старая стандартная библиотека шаблонов для С++ (в основном встроенная в стандартную библиотеку) была способом введения большого количества контейнеров и алгоритмов, которые работали так, как если бы они были встроены в язык, по крайней мере, с точки зрения интеграции и эффективности ( не синтаксически).

Ответ 11

Мы часто используем метапрограммирование для создания свойств в VBA. У нас есть различные электронные таблицы Excel со многими заголовками, и мы хотим определить свойства getter/setter для каждого заголовка, что позволяет нам манипулировать ячейками под этим заголовком. Вручную это было бы кошмаром.

Основой метапрограммирования для нас была Notepad++ и возможности поиска/замены регулярных выражений. Вот как мы запрограммировали наши свойства:

  • Скопируйте список заголовков из Excel в Notepad++
  • Запишите макрос Notepad++ для очистки данных (удалите пробелы и специальные символы). В конце этого у нас есть список разделенных строк новой строки.
  • Вручную скопируйте список в другой файл .CSV и используйте Excel для создания списка номеров строк. Затем скопируйте обратно в Notepad++.
  • Напишите регулярное выражение для преобразования имени свойства в определение свойства, добавив все пробелы, ключевые слова и т.д. Используйте номер строки в качестве номера столбца в нашем определении свойства.

В конце этого у нас есть процесс, который представляет собой смесь ручных шагов, записанных макросов и регулярных выражений, которые мы можем повторно применять каждый раз, когда нам нужны свойства для листа. И мы сделали! Для большого эффекта.

Это сила метапрограммирования. Когда использовать это вопрос опыта/интуиции. Но я рекомендую ответить на этот вопрос:

Будет ли быстрее для меня просто написать это напрямую, или я могу автоматизировать некоторые/все процессы и ускорить мой процесс?

Это дает вам черту, за которой метапрограммирование больше не нужно. Если вы можете просто кодировать это быстрее, даже если это 10 повторений, просто сделайте это! Только если это сотни повторений или что-то, что вы ожидаете многократно использовать в будущем, то запрограммируйте это.

Другое дело, что здесь есть градусы. Однажды я написал Java-программу для создания группы файлов для добавления новой проверки IntelliJ в проект кодирования проверок. Это было довольно трудоемко: создать проект Java, скомпилировать его и т.д. С другой стороны, Notepad++ find/replace - это всего лишь маленький шаг выше, чем вводить вещи вручную. Совет здесь состоит в том, чтобы начать делать вещи вручную, а затем автоматизировать, когда вы видите необходимость, только до такой степени, когда это имеет смысл. Нет необходимости в Java-программе, когда Notepad++ подойдет. Нет необходимости в Notepad++ при ручной печати.